M admin/input.go => admin/input.go +2 -2
@@ 57,7 57,7 @@ func (ui *UserInvitationForm) Validate(c echo.Context) error {
type DomainForm struct {
Name string `form:"name" validate:"required"`
LookupName string `form:"lookup_name" validate:"required"`
- Service int `form:"service" validate:"oneof=0 1 2"`
+ Service string `form:"service" validate:"oneof=LINKS SHORT LIST"`
Level string `form:"level" validate:"oneof=SYSTEM USER"`
Status int `form:"status" validate:"oneof=0 1 2"`
IsActive bool `form:"is_active"`
@@ 71,7 71,7 @@ func (d *DomainForm) Validate(c echo.Context) error {
FailFast(false).
String("name", &d.Name).
String("lookup_name", &d.LookupName).
- Int("service", &d.Service).
+ String("service", &d.Service).
String("level", &d.Level).
Int("status", &d.Status).
String("org_slug", &d.OrgSlug).
M admin/routes.go => admin/routes.go +3 -3
@@ 608,7 608,7 @@ func (s *Service) DomainUpdate(c echo.Context) error {
pd.Data["migrate_short_links"] = lt.Translate("Migrate Short Links")
pd.Data["migrate_warning"] = lt.Translate("Old links won't work. All code will be moved to the new domain.")
pd.Data["is_active"] = lt.Translate("Is Active")
- serviceOpt := map[int]string{
+ serviceOpt := map[string]string{
models.DomainServiceLinks: lt.Translate("Links"),
models.DomainServiceShort: lt.Translate("Link Shortner"),
models.DomainServiceList: lt.Translate("Link Listing"),
@@ 737,7 737,7 @@ func (s *Service) DomainCreate(c echo.Context) error {
pd.Data["migrate_short_links"] = lt.Translate("Migrate Short Links")
pd.Data["migrate_warning"] = lt.Translate("Old links won't work. All code will be moved to the new domain.")
pd.Data["is_active"] = lt.Translate("Is Active")
- serviceOpt := map[int]string{
+ serviceOpt := map[string]string{
models.DomainServiceLinks: lt.Translate("Links"),
models.DomainServiceShort: lt.Translate("Link Shortner"),
models.DomainServiceList: lt.Translate("Link Listing"),
@@ 1061,7 1061,7 @@ func (s *Service) DomainList(c echo.Context) error {
models.DomainLevelSystem: lt.Translate("System"),
models.DomainLevelUser: lt.Translate("User"),
}
- filterService := map[int]string{
+ filterService := map[string]string{
models.DomainServiceLinks: lt.Translate("Links"),
models.DomainServiceShort: lt.Translate("Shorts"),
models.DomainServiceList: lt.Translate("List"),
M api/api_test.go => api/api_test.go +4 -4
@@ 952,7 952,7 @@ func TestAPI(t *testing.T) {
}
op := gqlclient.NewOperation(
- `mutation AddDomain($name: String!, $lookupName: String!, $orgSlug: String!, $service: Int!) {
+ `mutation AddDomain($name: String!, $lookupName: String!, $orgSlug: String!, $service: DomainService!) {
addDomain(input: {name: $name, lookupName: $lookupName, orgSlug: $orgSlug, service: $service}) {
id
}
@@ 960,7 960,7 @@ func TestAPI(t *testing.T) {
op.Var("name", "Domain")
op.Var("lookupName", "app.testing.com")
op.Var("orgSlug", "personal-org")
- op.Var("service", 0)
+ op.Var("service", "LINKS")
var result GraphQLResponse
err := links.Execute(ctx, op, &result)
@@ 2095,7 2095,7 @@ func TestAPI(t *testing.T) {
}
op := gqlclient.NewOperation(
- `mutation AddDomain($name: String!, $lookupName: String!, $orgSlug: String!, $service: Int!) {
+ `mutation AddDomain($name: String!, $lookupName: String!, $orgSlug: String!, $service: DomainService!) {
addDomain(input: {name: $name, lookupName: $lookupName, orgSlug: $orgSlug, service: $service}) {
id
}
@@ 2103,7 2103,7 @@ func TestAPI(t *testing.T) {
op.Var("name", "Domain 2")
op.Var("lookupName", "app.domain.com")
op.Var("orgSlug", "personal-org")
- op.Var("service", 0)
+ op.Var("service", "LIST")
var result GraphQLResponse
err := links.Execute(ctx, op, &result)
M api/graph/generated.go => api/graph/generated.go +77 -20
@@ 365,7 365,7 @@ type ComplexityRoot struct {
GetAdminOrgStats func(childComplexity int, id int) int
GetAdminOrganizations func(childComplexity int, input *model.GetAdminOrganizationsInput) int
GetDomain func(childComplexity int, id int) int
- GetDomains func(childComplexity int, orgSlug *string, service *int) int
+ GetDomains func(childComplexity int, orgSlug *string, service *model.DomainService) int
GetFeed func(childComplexity int, input *model.GetFeedInput) int
GetFeedFollowing func(childComplexity int) int
GetLinkShort func(childComplexity int, shortCode string, domainID *int) int
@@ 433,7 433,7 @@ type ComplexityRoot struct {
type DomainResolver interface {
OrgID(ctx context.Context, obj *models.Domain) (*model.NullInt, error)
OrgSlug(ctx context.Context, obj *models.Domain) (*model.NullString, error)
-
+ Service(ctx context.Context, obj *models.Domain) (model.DomainService, error)
Level(ctx context.Context, obj *models.Domain) (model.DomainLevel, error)
}
type MutationResolver interface {
@@ 486,7 486,7 @@ type QueryResolver interface {
GetOrgLink(ctx context.Context, hash string) (*models.OrgLink, error)
GetOrgLinks(ctx context.Context, input *model.GetLinkInput) (*model.OrgLinkCursor, error)
GetOrgMembers(ctx context.Context, orgSlug string) ([]*models.User, error)
- GetDomains(ctx context.Context, orgSlug *string, service *int) ([]*models.Domain, error)
+ GetDomains(ctx context.Context, orgSlug *string, service *model.DomainService) ([]*models.Domain, error)
GetDomain(ctx context.Context, id int) (*models.Domain, error)
GetLinkShorts(ctx context.Context, input *model.GetLinkShortInput) (*model.LinkShortCursor, error)
GetLinkShort(ctx context.Context, shortCode string, domainID *int) (*models.LinkShort, error)
@@ 2177,7 2177,7 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
return 0, false
}
- return e.complexity.Query.GetDomains(childComplexity, args["orgSlug"].(*string), args["service"].(*int)), true
+ return e.complexity.Query.GetDomains(childComplexity, args["orgSlug"].(*string), args["service"].(*model.DomainService)), true
case "Query.getFeed":
if e.complexity.Query.GetFeed == nil {
@@ 3376,10 3376,10 @@ func (ec *executionContext) field_Query_getDomains_args(ctx context.Context, raw
}
}
args["orgSlug"] = arg0
- var arg1 *int
+ var arg1 *model.DomainService
if tmp, ok := rawArgs["service"]; ok {
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("service"))
- arg1, err = ec.unmarshalOInt2ᚖint(ctx, tmp)
+ arg1, err = ec.unmarshalODomainService2ᚖlinksᚋapiᚋgraphᚋmodelᚐDomainService(ctx, tmp)
if err != nil {
return nil, err
}
@@ 5637,7 5637,7 @@ func (ec *executionContext) _Domain_service(ctx context.Context, field graphql.C
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
- return obj.Service, nil
+ return ec.resolvers.Domain().Service(rctx, obj)
})
if err != nil {
ec.Error(ctx, err)
@@ 5649,19 5649,19 @@ func (ec *executionContext) _Domain_service(ctx context.Context, field graphql.C
}
return graphql.Null
}
- res := resTmp.(int)
+ res := resTmp.(model.DomainService)
fc.Result = res
- return ec.marshalNInt2int(ctx, field.Selections, res)
+ return ec.marshalNDomainService2linksᚋapiᚋgraphᚋmodelᚐDomainService(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Domain_service(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Domain",
Field: field,
- IsMethod: false,
- IsResolver: false,
+ IsMethod: true,
+ IsResolver: true,
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
- return nil, errors.New("field of type Int does not have child fields")
+ return nil, errors.New("field of type DomainService does not have child fields")
},
}
return fc, nil
@@ 16758,7 16758,7 @@ func (ec *executionContext) _Query_getDomains(ctx context.Context, field graphql
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
directive0 := func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
- return ec.resolvers.Query().GetDomains(rctx, fc.Args["orgSlug"].(*string), fc.Args["service"].(*int))
+ return ec.resolvers.Query().GetDomains(rctx, fc.Args["orgSlug"].(*string), fc.Args["service"].(*model.DomainService))
}
directive1 := func(ctx context.Context) (interface{}, error) {
scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "DOMAINS")
@@ 21762,7 21762,7 @@ func (ec *executionContext) unmarshalInputAdminDomainInput(ctx context.Context,
it.OrgSlug = data
case "service":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("service"))
- data, err := ec.unmarshalNInt2int(ctx, v)
+ data, err := ec.unmarshalNDomainService2linksᚋapiᚋgraphᚋmodelᚐDomainService(ctx, v)
if err != nil {
return it, err
}
@@ 21948,7 21948,7 @@ func (ec *executionContext) unmarshalInputDomainInput(ctx context.Context, obj i
it.OrgSlug = data
case "service":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("service"))
- data, err := ec.unmarshalNInt2int(ctx, v)
+ data, err := ec.unmarshalNDomainService2linksᚋapiᚋgraphᚋmodelᚐDomainService(ctx, v)
if err != nil {
return it, err
}
@@ 22017,7 22017,7 @@ func (ec *executionContext) unmarshalInputGetAdminDomainInput(ctx context.Contex
it.FilterLevel = data
case "filterService":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("filterService"))
- data, err := ec.unmarshalOInt2ᚖint(ctx, v)
+ data, err := ec.unmarshalODomainService2ᚖlinksᚋapiᚋgraphᚋmodelᚐDomainService(ctx, v)
if err != nil {
return it, err
}
@@ 23070,7 23070,7 @@ func (ec *executionContext) unmarshalInputUpdateAdminDomainInput(ctx context.Con
it.OrgSlug = data
case "service":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("service"))
- data, err := ec.unmarshalNInt2int(ctx, v)
+ data, err := ec.unmarshalNDomainService2linksᚋapiᚋgraphᚋmodelᚐDomainService(ctx, v)
if err != nil {
return it, err
}
@@ 24074,10 24074,41 @@ func (ec *executionContext) _Domain(ctx context.Context, sel ast.SelectionSet, o
out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
case "service":
- out.Values[i] = ec._Domain_service(ctx, field, obj)
- if out.Values[i] == graphql.Null {
- atomic.AddUint32(&out.Invalids, 1)
+ field := field
+
+ innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
+ defer func() {
+ if r := recover(); r != nil {
+ ec.Error(ctx, ec.Recover(ctx, r))
+ }
+ }()
+ res = ec._Domain_service(ctx, field, obj)
+ if res == graphql.Null {
+ atomic.AddUint32(&fs.Invalids, 1)
+ }
+ return res
}
+
+ if field.Deferrable != nil {
+ dfs, ok := deferred[field.Deferrable.Label]
+ di := 0
+ if ok {
+ dfs.AddField(field)
+ di = len(dfs.Values) - 1
+ } else {
+ dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
+ deferred[field.Deferrable.Label] = dfs
+ }
+ dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
+ return innerFunc(ctx, dfs)
+ })
+
+ // don't run the out.Concurrently() call below
+ out.Values[i] = graphql.Null
+ continue
+ }
+
+ out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
case "level":
field := field
@@ 27418,6 27449,16 @@ func (ec *executionContext) marshalNDomainLevel2linksᚋapiᚋgraphᚋmodelᚐDo
return v
}
+func (ec *executionContext) unmarshalNDomainService2linksᚋapiᚋgraphᚋmodelᚐDomainService(ctx context.Context, v interface{}) (model.DomainService, error) {
+ var res model.DomainService
+ err := res.UnmarshalGQL(v)
+ return res, graphql.ErrorOnPath(ctx, err)
+}
+
+func (ec *executionContext) marshalNDomainService2linksᚋapiᚋgraphᚋmodelᚐDomainService(ctx context.Context, sel ast.SelectionSet, v model.DomainService) graphql.Marshaler {
+ return v
+}
+
func (ec *executionContext) marshalNFollowPayload2linksᚋapiᚋgraphᚋmodelᚐFollowPayload(ctx context.Context, sel ast.SelectionSet, v model.FollowPayload) graphql.Marshaler {
return ec._FollowPayload(ctx, sel, &v)
}
@@ 28534,6 28575,22 @@ func (ec *executionContext) marshalODomainLevel2ᚖlinksᚋapiᚋgraphᚋmodel
return v
}
+func (ec *executionContext) unmarshalODomainService2ᚖlinksᚋapiᚋgraphᚋmodelᚐDomainService(ctx context.Context, v interface{}) (*model.DomainService, error) {
+ if v == nil {
+ return nil, nil
+ }
+ var res = new(model.DomainService)
+ err := res.UnmarshalGQL(v)
+ return res, graphql.ErrorOnPath(ctx, err)
+}
+
+func (ec *executionContext) marshalODomainService2ᚖlinksᚋapiᚋgraphᚋmodelᚐDomainService(ctx context.Context, sel ast.SelectionSet, v *model.DomainService) graphql.Marshaler {
+ if v == nil {
+ return graphql.Null
+ }
+ return v
+}
+
func (ec *executionContext) unmarshalOGetAdminDomainInput2ᚖlinksᚋapiᚋgraphᚋmodelᚐGetAdminDomainInput(ctx context.Context, v interface{}) (*model.GetAdminDomainInput, error) {
if v == nil {
return nil, nil
M api/graph/model/models_gen.go => api/graph/model/models_gen.go +73 -30
@@ 67,14 67,14 @@ type AdminBillingStats struct {
}
type AdminDomainInput struct {
- Name string `json:"name"`
- LookupName string `json:"lookupName"`
- OrgSlug *string `json:"orgSlug,omitempty"`
- Service int `json:"service"`
- Level DomainLevel `json:"level"`
- Status int `json:"status"`
- IsActive bool `json:"isActive"`
- MigrateLinks *bool `json:"migrateLinks,omitempty"`
+ Name string `json:"name"`
+ LookupName string `json:"lookupName"`
+ OrgSlug *string `json:"orgSlug,omitempty"`
+ Service DomainService `json:"service"`
+ Level DomainLevel `json:"level"`
+ Status int `json:"status"`
+ IsActive bool `json:"isActive"`
+ MigrateLinks *bool `json:"migrateLinks,omitempty"`
}
type AnalyticData struct {
@@ 120,11 120,11 @@ type DomainCursor struct {
}
type DomainInput struct {
- Name string `json:"name"`
- LookupName string `json:"lookupName"`
- OrgSlug string `json:"orgSlug"`
- Service int `json:"service"`
- MigrateLinks *bool `json:"migrateLinks,omitempty"`
+ Name string `json:"name"`
+ LookupName string `json:"lookupName"`
+ OrgSlug string `json:"orgSlug"`
+ Service DomainService `json:"service"`
+ MigrateLinks *bool `json:"migrateLinks,omitempty"`
}
type FollowPayload struct {
@@ 133,14 133,14 @@ type FollowPayload struct {
}
type GetAdminDomainInput struct {
- Limit *int `json:"limit,omitempty"`
- After *Cursor `json:"after,omitempty"`
- Before *Cursor `json:"before,omitempty"`
- Search *string `json:"search,omitempty"`
- FilterLevel *DomainLevel `json:"filterLevel,omitempty"`
- FilterService *int `json:"filterService,omitempty"`
- FilterActive *bool `json:"filterActive,omitempty"`
- OrgSlug *string `json:"orgSlug,omitempty"`
+ Limit *int `json:"limit,omitempty"`
+ After *Cursor `json:"after,omitempty"`
+ Before *Cursor `json:"before,omitempty"`
+ Search *string `json:"search,omitempty"`
+ FilterLevel *DomainLevel `json:"filterLevel,omitempty"`
+ FilterService *DomainService `json:"filterService,omitempty"`
+ FilterActive *bool `json:"filterActive,omitempty"`
+ OrgSlug *string `json:"orgSlug,omitempty"`
}
type GetAdminOrganizationsInput struct {
@@ 372,15 372,15 @@ type RegisterInvitation struct {
}
type UpdateAdminDomainInput struct {
- ID int `json:"id"`
- Name string `json:"name"`
- LookupName string `json:"lookupName"`
- OrgSlug *string `json:"orgSlug,omitempty"`
- Service int `json:"service"`
- Level DomainLevel `json:"level"`
- Status int `json:"status"`
- IsActive bool `json:"isActive"`
- MigrateLinks *bool `json:"migrateLinks,omitempty"`
+ ID int `json:"id"`
+ Name string `json:"name"`
+ LookupName string `json:"lookupName"`
+ OrgSlug *string `json:"orgSlug,omitempty"`
+ Service DomainService `json:"service"`
+ Level DomainLevel `json:"level"`
+ Status int `json:"status"`
+ IsActive bool `json:"isActive"`
+ MigrateLinks *bool `json:"migrateLinks,omitempty"`
}
type UpdateLinkInput struct {
@@ 596,3 596,46 @@ func (e *DomainLevel) UnmarshalGQL(v interface{}) error {
func (e DomainLevel) MarshalGQL(w io.Writer) {
fmt.Fprint(w, strconv.Quote(e.String()))
}
+
+type DomainService string
+
+const (
+ DomainServiceLinks DomainService = "LINKS"
+ DomainServiceShort DomainService = "SHORT"
+ DomainServiceList DomainService = "LIST"
+)
+
+var AllDomainService = []DomainService{
+ DomainServiceLinks,
+ DomainServiceShort,
+ DomainServiceList,
+}
+
+func (e DomainService) IsValid() bool {
+ switch e {
+ case DomainServiceLinks, DomainServiceShort, DomainServiceList:
+ return true
+ }
+ return false
+}
+
+func (e DomainService) String() string {
+ return string(e)
+}
+
+func (e *DomainService) UnmarshalGQL(v interface{}) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+
+ *e = DomainService(str)
+ if !e.IsValid() {
+ return fmt.Errorf("%s is not a valid DomainService", str)
+ }
+ return nil
+}
+
+func (e DomainService) MarshalGQL(w io.Writer) {
+ fmt.Fprint(w, strconv.Quote(e.String()))
+}
M api/graph/schema.graphqls => api/graph/schema.graphqls +13 -6
@@ 68,6 68,13 @@ enum DomainLevel {
USER
}
+enum DomainService {
+ LINKS
+ SHORT
+ LIST
+}
+
+
# Considering removing these Null* fields:
# https://todo.code.netlandish.com/~netlandish/links/75
@@ 247,7 254,7 @@ type Domain {
lookupName: String!
orgId: NullInt! @access(scope: DOMAINS, kind: RO)
orgSlug: NullString! @access(scope: DOMAINS, kind: RO)
- service: Int!
+ service: DomainService!
level: DomainLevel!
status: Int!
isActive: Boolean! @access(scope: DOMAINS, kind: RO)
@@ 455,7 462,7 @@ input GetAdminDomainInput {
before: Cursor
search: String
filterLevel: DomainLevel
- filterService: Int
+ filterService: DomainService
filterActive: Boolean
orgSlug: String
}
@@ 624,7 631,7 @@ input DomainInput {
name: String!
lookupName: String!
orgSlug: String!
- service: Int!
+ service: DomainService!
migrateLinks: Boolean
}
@@ 632,7 639,7 @@ input AdminDomainInput {
name: String!
lookupName: String!
orgSlug: String
- service: Int!
+ service: DomainService!
level: DomainLevel!
status: Int!
isActive: Boolean!
@@ 644,7 651,7 @@ input UpdateAdminDomainInput {
name: String!
lookupName: String!
orgSlug: String
- service: Int!
+ service: DomainService!
level: DomainLevel!
status: Int!
isActive: Boolean!
@@ 703,7 710,7 @@ type Query {
getOrgMembers(orgSlug: String!): [User]! @access(scope: ORGS, kind: RO)
"Returns custom domains of an organization"
- getDomains(orgSlug: String, service: Int): [Domain]! @access(scope: DOMAINS, kind: RO)
+ getDomains(orgSlug: String, service: DomainService): [Domain]! @access(scope: DOMAINS, kind: RO)
"Returns a specific domain"
getDomain(id: Int!): Domain! @access(scope: DOMAINS, kind: RO)
M api/graph/schema.resolvers.go => api/graph/schema.resolvers.go +21 -19
@@ 60,9 60,14 @@ func (r *domainResolver) OrgSlug(ctx context.Context, obj *models.Domain) (*mode
return &model.NullString{String: obj.OrgSlug.String, Valid: obj.OrgSlug.Valid}, nil
}
+// Service is the resolver for the service field.
+func (r *domainResolver) Service(ctx context.Context, obj *models.Domain) (model.DomainService, error) {
+ return model.DomainService(obj.Service), nil
+}
+
// Level is the resolver for the level field.
func (r *domainResolver) Level(ctx context.Context, obj *models.Domain) (model.DomainLevel, error) {
- panic(fmt.Errorf("not implemented: Level - level"))
+ return model.DomainLevel(obj.Level), nil
}
// AddOrganization is the resolver for the addOrganization field.
@@ 1735,8 1740,7 @@ func (r *mutationResolver) AddDomain(ctx context.Context, input model.DomainInpu
lt.Translate("Invalid domain name.")).
WithField("lookupName").
WithCode(valid.ErrValidationCode)
- validator.Expect(input.Service >= models.DomainServiceLinks &&
- input.Service <= models.DomainServiceList,
+ validator.Expect(domain.ValidateDomainService(string(input.Service)),
lt.Translate("Invalid service value.")).
WithField("service").
WithCode(valid.ErrValidationCode)
@@ 1818,7 1822,7 @@ func (r *mutationResolver) AddDomain(ctx context.Context, input model.DomainInpu
return nil, nil
}
- dnsOK, err := domain.CheckDomainDNS(ctx, host, input.Service)
+ dnsOK, err := domain.CheckDomainDNS(ctx, host, string(input.Service))
if err != nil {
validator.Error(
lt.Translate("Error checking the DNS entry for domain. Please try again later")).
@@ 1838,7 1842,7 @@ func (r *mutationResolver) AddDomain(ctx context.Context, input model.DomainInpu
LookupName: host,
OrgID: sql.NullInt64{Int64: int64(org.ID), Valid: true},
Level: models.DomainLevelUser,
- Service: input.Service,
+ Service: string(input.Service),
Status: models.DomainStatusApproved,
IsActive: true,
}
@@ 1847,7 1851,7 @@ func (r *mutationResolver) AddDomain(ctx context.Context, input model.DomainInpu
return nil, err
}
- if input.MigrateLinks != nil && *input.MigrateLinks && input.Service == models.DomainServiceShort {
+ if input.MigrateLinks != nil && *input.MigrateLinks && string(input.Service) == models.DomainServiceShort {
err = models.MigrateLinkShorts(ctx, domain.ID, int(domain.OrgID.Int64))
if err != nil {
return nil, err
@@ 3701,8 3705,7 @@ func (r *mutationResolver) AddAdminDomain(ctx context.Context, input model.Admin
lt.Translate("Invalid domain name.")).
WithField("lookupName").
WithCode(valid.ErrValidationCode)
- validator.Expect(input.Service >= models.DomainServiceLinks &&
- input.Service <= models.DomainServiceList,
+ validator.Expect(domain.ValidateDomainService(string(input.Service)),
lt.Translate("Invalid service value.")).
WithField("service").
WithCode(valid.ErrValidationCode)
@@ 3712,7 3715,7 @@ func (r *mutationResolver) AddAdminDomain(ctx context.Context, input model.Admin
WithField("level").
WithCode(valid.ErrValidationCode)
validator.Expect(input.Status >= models.DomainStatusPending &&
- input.Service <= models.DomainStatusError,
+ input.Status <= models.DomainStatusError,
lt.Translate("Invalid status value.")).
WithField("status").
WithCode(valid.ErrValidationCode)
@@ 3810,7 3813,7 @@ func (r *mutationResolver) AddAdminDomain(ctx context.Context, input model.Admin
}
}
- dnsOK, err := domain.CheckDomainDNS(ctx, host, input.Service)
+ dnsOK, err := domain.CheckDomainDNS(ctx, host, string(input.Service))
if err != nil {
validator.Error(
lt.Translate("Error checking the DNS entry for domain. Please try again later")).
@@ 3829,7 3832,7 @@ func (r *mutationResolver) AddAdminDomain(ctx context.Context, input model.Admin
Name: input.Name,
LookupName: host,
Level: string(input.Level),
- Service: input.Service,
+ Service: string(input.Service),
Status: input.Status,
IsActive: input.IsActive,
}
@@ 3841,7 3844,7 @@ func (r *mutationResolver) AddAdminDomain(ctx context.Context, input model.Admin
return nil, err
}
- if input.MigrateLinks != nil && *input.MigrateLinks && input.Service == models.DomainServiceShort {
+ if input.MigrateLinks != nil && *input.MigrateLinks && string(input.Service) == models.DomainServiceShort {
err = models.MigrateLinkShorts(ctx, domain.ID, int(domain.OrgID.Int64))
if err != nil {
return nil, err
@@ 3877,8 3880,7 @@ func (r *mutationResolver) UpdateAdminDomain(ctx context.Context, input model.Up
lt.Translate("Invalid ID ")).
WithField("id").
WithCode(valid.ErrValidationCode)
- validator.Expect(input.Service >= models.DomainServiceLinks &&
- input.Service <= models.DomainServiceList,
+ validator.Expect(domain.ValidateDomainService(string(input.Service)),
lt.Translate("Invalid service value.")).
WithField("service").
WithCode(valid.ErrValidationCode)
@@ 3888,7 3890,7 @@ func (r *mutationResolver) UpdateAdminDomain(ctx context.Context, input model.Up
WithField("level").
WithCode(valid.ErrValidationCode)
validator.Expect(input.Status >= models.DomainStatusPending &&
- input.Service <= models.DomainStatusError,
+ input.Status <= models.DomainStatusError,
lt.Translate("Invalid status value.")).
WithField("status").
WithCode(valid.ErrValidationCode)
@@ 4006,7 4008,7 @@ func (r *mutationResolver) UpdateAdminDomain(ctx context.Context, input model.Up
}
}
- dnsOK, err := domain.CheckDomainDNS(ctx, host, input.Service)
+ dnsOK, err := domain.CheckDomainDNS(ctx, host, string(input.Service))
if err != nil {
validator.Error(
lt.Translate("Error checking the DNS entry for domain. Please try again later")).
@@ 4024,7 4026,7 @@ func (r *mutationResolver) UpdateAdminDomain(ctx context.Context, input model.Up
ldomain.Name = input.Name
ldomain.LookupName = host
ldomain.Level = string(input.Level)
- ldomain.Service = input.Service
+ ldomain.Service = string(input.Service)
ldomain.Status = input.Status
ldomain.IsActive = input.IsActive
@@ 4036,7 4038,7 @@ func (r *mutationResolver) UpdateAdminDomain(ctx context.Context, input model.Up
return nil, err
}
- if input.MigrateLinks != nil && *input.MigrateLinks && input.Service == models.DomainServiceShort {
+ if input.MigrateLinks != nil && *input.MigrateLinks && string(input.Service) == models.DomainServiceShort {
err = models.MigrateLinkShorts(ctx, ldomain.ID, int(ldomain.OrgID.Int64))
if err != nil {
return nil, err
@@ 4815,7 4817,7 @@ func (r *queryResolver) GetOrgMembers(ctx context.Context, orgSlug string) ([]*m
}
// GetDomains is the resolver for the getDomains field.
-func (r *queryResolver) GetDomains(ctx context.Context, orgSlug *string, service *int) ([]*models.Domain, error) {
+func (r *queryResolver) GetDomains(ctx context.Context, orgSlug *string, service *model.DomainService) ([]*models.Domain, error) {
tokenUser := oauth2.ForContext(ctx)
if tokenUser == nil {
return nil, valid.ErrAuthorization
M cmd/domains/main.go => cmd/domains/main.go +1 -1
@@ 56,7 56,7 @@ func run() error {
if dom == "" {
return c.NoContent(http.StatusBadRequest)
}
- domains, err := domain.ValidDomain(c.Request().Context(), dom, -1, true)
+ domains, err := domain.ValidDomain(c.Request().Context(), dom, "", true)
if err != nil {
return err
}
M cmd/server.go => cmd/server.go +1 -1
@@ 189,7 189,7 @@ func LoadStorageService(config *config.Config) (storage.Service, error) {
}
// LoadAutoTLS ...
-func LoadAutoTLS(config *config.Config, db *sql.DB, service int) *autocert.Manager {
+func LoadAutoTLS(config *config.Config, db *sql.DB, service string) *autocert.Manager {
autotls, ok := config.File.Get("links", "auto-tls")
if ok && autotls == "false" {
// Enabled by default
M core/inputs.go => core/inputs.go +2 -2
@@ 142,7 142,7 @@ func (l *LinkForm) Validate(c echo.Context) error {
type DomainForm struct {
Name string `form:"name" validate:"required"`
LookupName string `form:"lookup_name" validate:"required"`
- Service int `form:"service" validate:"oneof=0 1 2"`
+ Service string `form:"service" validate:"oneof=LINKS SHORT LIST"`
MigrateLinks bool `form:"migrate_links"`
}
@@ 152,7 152,7 @@ func (d *DomainForm) Validate(c echo.Context) error {
FailFast(false).
String("name", &d.Name).
String("lookup_name", &d.LookupName).
- Int("service", &d.Service).
+ String("service", &d.Service).
Bool("migrate_links", &d.MigrateLinks).
BindErrors()
if errs != nil {
M core/routes.go => core/routes.go +1 -1
@@ 466,7 466,7 @@ func (s *Service) DomainCreate(c echo.Context) error {
pd.Data["for"] = lt.Translate("for")
pd.Data["migrate_short_links"] = lt.Translate("Migrate Short Links")
pd.Data["migrate_warning"] = lt.Translate("Old links won't work. All code will be moved to the new domain.")
- serviceOpt := map[int]string{
+ serviceOpt := map[string]string{
models.DomainServiceLinks: lt.Translate("Links"),
models.DomainServiceShort: lt.Translate("Link Shortner"),
models.DomainServiceList: lt.Translate("Link Listing"),
M core/routes_test.go => core/routes_test.go +2 -2
@@ 344,7 344,7 @@ func TestHandlers(t *testing.T) {
f := make(url.Values)
f.Set("lookup_name", "app.links.org")
- f.Set("service", "1")
+ f.Set("service", "SHORT")
f.Set("name", "app links")
request := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(f.Encode()))
request.Header.Set(echo.HeaderContentType, echo.MIMEApplicationForm)
@@ 371,7 371,7 @@ func TestHandlers(t *testing.T) {
f := make(url.Values)
f.Set("lookup_name", "app.links.org")
- f.Set("service", "1")
+ f.Set("service", "SHORT")
f.Set("name", "app links")
request := httptest.NewRequest(http.MethodPost, "/", strings.NewReader(f.Encode()))
request.Header.Set(echo.HeaderContentType, echo.MIMEApplicationForm)
M core/samples/create_domain.json => core/samples/create_domain.json +1 -1
@@ 3,7 3,7 @@
"addDomain": {
"id": 1,
"lookup_name": "app.links.org",
- "service": 0,
+ "service": "LINKS",
"org_id": 1
}
}
M core/samples/domain_list.json => core/samples/domain_list.json +2 -2
@@ 6,14 6,14 @@
"name": "Domain one",
"lookup_name": "app.links.com",
"org_id": 1,
- "service": 0
+ "service": "LINKS"
},
{
"id": 2,
"name": "Domain two",
"lookup_name": "app.links_two.com",
"org_id": 1,
- "service": 1
+ "service": "SHORT"
}
]
}
M domain/logic.go => domain/logic.go +22 -13
@@ 18,7 18,7 @@ import (
var ipMap map[string]net.IP
func ValidDomain(
- ctx context.Context, host string, service int, active bool) ([]*models.Domain, error) {
+ ctx context.Context, host string, service string, active bool) ([]*models.Domain, error) {
// Remove :PORT from host name
host = strings.SplitN(host, ":", 2)[0]
h, err := idna.Lookup.ToASCII(host)
@@ 32,7 32,7 @@ func ValidDomain(
sq.Eq{"d.status": models.DomainStatusApproved},
},
}
- if service >= 0 {
+ if service != "" {
opts.Filter = sq.And{
opts.Filter,
sq.Eq{"d.service": service},
@@ 53,7 53,7 @@ func ValidDomain(
// DomainHostPolicy returns a autocert manager HostPolicy instance to work
// with confiugred domains for various services
-func DomainHostPolicy(db *sql.DB, service int) autocert.HostPolicy {
+func DomainHostPolicy(db *sql.DB, service string) autocert.HostPolicy {
return func(ctx context.Context, host string) error {
ctx = database.Context(ctx, db)
domains, err := ValidDomain(ctx, host, service, true)
@@ 68,9 68,11 @@ func DomainHostPolicy(db *sql.DB, service int) autocert.HostPolicy {
}
// CheckDomainDNS will verify a domain has a proper CNAME set
-func CheckDomainDNS(ctx context.Context, domain string, service int) (bool, error) {
- if service < models.DomainServiceLinks || service > models.DomainServiceList {
- return false, fmt.Errorf("invalid service type given")
+func CheckDomainDNS(ctx context.Context, domain string, service string) (bool, error) {
+ serviceMap := map[string]string{
+ models.DomainServiceLinks: "links-cname-domain",
+ models.DomainServiceShort: "short-cname-domain",
+ models.DomainServiceList: "list-cname-domain",
}
var (
@@ 85,13 87,9 @@ func CheckDomainDNS(ctx context.Context, domain string, service int) (bool, erro
return true, nil
}
- switch service {
- case models.DomainServiceLinks:
- cval = "links-cname-domain"
- case models.DomainServiceShort:
- cval = "short-cname-domain"
- case models.DomainServiceList:
- cval = "list-cname-domain"
+ cval, ok = serviceMap[service]
+ if !ok {
+ return false, fmt.Errorf("invalid service type given")
}
expName, ok = srv.Config.File.Get("links", cval)
@@ 128,3 126,14 @@ func CheckDomainDNS(ctx context.Context, domain string, service int) (bool, erro
return true, nil
}
+
+// ValidateDomainService is a helper to verify the service given is valid
+func ValidateDomainService(service string) bool {
+ serviceMap := map[string]bool{
+ models.DomainServiceLinks: true,
+ models.DomainServiceShort: true,
+ models.DomainServiceList: true,
+ }
+ _, ok := serviceMap[service]
+ return ok
+}
M domain/middleware.go => domain/middleware.go +1 -1
@@ 49,7 49,7 @@ func badDomainRedirect(c echo.Context, d string) error {
}
// DomainContext adds the current domain to request context.
-func DomainContext(service int) echo.MiddlewareFunc {
+func DomainContext(service string) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
req := c.Request()
M migrations/0001_initial.down.sql => migrations/0001_initial.down.sql +1 -0
@@ 33,3 33,4 @@ DROP TABLE IF EXISTS organizations;
DROP TABLE IF EXISTS users;
DROP TYPE IF EXISTS domain_level;
+DROP TYPE IF EXISTS domain_service;
M migrations/0001_initial.up.sql => migrations/0001_initial.up.sql +12 -1
@@ 20,6 20,17 @@ EXCEPTION
WHEN duplicate_object THEN null;
END $$;
+DO $$ BEGIN
+ CREATE TYPE domain_service AS ENUM (
+ 'LINKS',
+ 'SHORT',
+ 'LIST'
+ );
+EXCEPTION
+ WHEN duplicate_object THEN null;
+END $$;
+
+
CREATE TABLE users (
id SERIAL PRIMARY KEY,
@@ 153,7 164,7 @@ CREATE TABLE domains (
lookup_name VARCHAR (500) NOT NULL, -- padded in case...
org_id INT REFERENCES organizations (id) ON DELETE CASCADE,
level domain_level NOT NULL,
- service INT NOT NULL,
+ service domain_service NOT NULL,
status INT DEFAULT 0 NOT NULL,
is_active BOOLEAN DEFAULT TRUE,
last_action TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
M migrations/test_migration.up.sql => migrations/test_migration.up.sql +2 -2
@@ 15,8 15,8 @@ INSERT INTO org_links (title, url, base_url_id, user_id, org_id, visibility, has
INSERT INTO org_links (title, url, base_url_id, user_id, org_id, visibility, hash) VALUES
('Private Business url', 'http://base.com?vis=private', 1, 1, 2, 1, 'hash2');
-INSERT INTO domains (name, lookup_name, org_id, level, service, status) VALUES ('short domain', 'short.domain.org', 1, 'SYSTEM', 1, 1);
-INSERT INTO domains (name, lookup_name, org_id, service, status, level) VALUES ('listing domain', 'list.domain.org', 1, 2, 1, 'USER');
+INSERT INTO domains (name, lookup_name, org_id, level, service, status) VALUES ('short domain', 'short.domain.org', 1, 'SYSTEM', 'SHORT', 1);
+INSERT INTO domains (name, lookup_name, org_id, service, status, level) VALUES ('listing domain', 'list.domain.org', 1, 'LIST', 1, 'USER');
INSERT INTO link_shorts (id, title, url, domain_id, org_id, short_code, user_id) VALUES (100, 'testing short', 'http://test.domain.org', 1, 1, 'foo', 1);
INSERT INTO listings (id, title, slug, domain_id, is_default, user_id, org_id) VALUES (100, 'test listing', 'test-listing-slug', 2, false, 1, 1);
M models/domains.go => models/domains.go +6 -3
@@ 22,11 22,11 @@ const (
const (
// DomainServiceLinks ...
- DomainServiceLinks int = iota
+ DomainServiceLinks string = "LINKS"
// DomainServiceShort ...
- DomainServiceShort
+ DomainServiceShort string = "SHORT"
// DomainServiceList ...
- DomainServiceList
+ DomainServiceList string = "LIST"
)
const (
@@ 137,6 137,9 @@ func (d *Domain) Store(ctx context.Context) error {
if d.Level == "" {
d.Level = DomainLevelSystem
}
+ if d.Service == "" {
+ d.Service = DomainServiceLinks
+ }
err = sq.
Insert("domains").
Columns("name", "lookup_name", "org_id", "level", "service", "status", "is_active").
M models/models.go => models/models.go +1 -1
@@ 110,7 110,7 @@ type Domain struct {
LookupName string `db:"lookup_name"`
OrgID sql.NullInt64 `db:"org_id"`
Level string `db:"level"`
- Service int `db:"service"`
+ Service string `db:"service"`
Status int `db:"status"`
IsActive bool `db:"is_active"`
LastAction time.Time `db:"last_action"`
M models/schema.sql => models/schema.sql +6 -1
@@ 15,6 15,11 @@ CREATE TYPE domain_level AS ENUM (
'USER'
);
+CREATE TYPE domain_service AS ENUM (
+ 'LINKS',
+ 'SHORT',
+ 'LIST'
+);
CREATE TABLE users (
id SERIAL PRIMARY KEY,
@@ 148,7 153,7 @@ CREATE TABLE domains (
lookup_name VARCHAR (500) NOT NULL, -- padded in case...
org_id INT REFERENCES organizations (id) ON DELETE CASCADE,
level domain_level NOT NULL,
- service INT NOT NULL,
+ service domain_service NOT NULL,
status INT DEFAULT 0 NOT NULL,
is_active BOOLEAN DEFAULT TRUE,
last_action TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
M templates/domain_list.html => templates/domain_list.html +3 -3
@@ 25,11 25,11 @@
<td>{{.Name}}</td>
<td>{{.LookupName}}</td>
<td>
- {{ if eq .Service 0 }}
+ {{ if .IsServiceLink }}
{{$.pd.Data.links}}
- {{ else if eq .Service 1 }}
+ {{ else if .IsServiceShort }}
{{$.pd.Data.link_shortner}}
- {{ else if eq .Service 2 }}
+ {{ else if .IsServiceList }}
{{$.pd.Data.link_listing}}
{{end}}
</td>