M admin/input.go => admin/input.go +2 -2
@@ 59,7 59,7 @@ type DomainForm struct {
LookupName string `form:"lookup_name" validate:"required"`
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"`
+ Status string `form:"status" validate:"oneof=PENDING APPROVED ERROR"`
IsActive bool `form:"is_active"`
OrgSlug string `form:"org_slug"`
MigrateLinks bool `form:"migrate_links"`
@@ 73,7 73,7 @@ func (d *DomainForm) Validate(c echo.Context) error {
String("lookup_name", &d.LookupName).
String("service", &d.Service).
String("level", &d.Level).
- Int("status", &d.Status).
+ String("status", &d.Status).
String("org_slug", &d.OrgSlug).
Bool("is_active", &d.IsActive).
Bool("migrate_links", &d.MigrateLinks).
M admin/routes.go => admin/routes.go +4 -4
@@ 618,7 618,7 @@ func (s *Service) DomainUpdate(c echo.Context) error {
models.DomainLevelSystem: lt.Translate("System"),
models.DomainLevelUser: lt.Translate("User"),
}
- statusOpt := map[int]string{
+ statusOpt := map[string]string{
models.DomainStatusPending: lt.Translate("Pending"),
models.DomainStatusApproved: lt.Translate("Approved"),
models.DomainStatusError: lt.Translate("Error"),
@@ 665,7 665,7 @@ func (s *Service) DomainUpdate(c echo.Context) error {
var result GraphQLResponse
op := gqlclient.NewOperation(
- `mutation UpdateAdminDomain($id: Int!, $name: String!, $lookupName: String!, $orgSlug: String, $level: DomainLevel!, $status: Int!
+ `mutation UpdateAdminDomain($id: Int!, $name: String!, $lookupName: String!, $orgSlug: String, $level: DomainLevel!, $status: DomainStatus!
$service: DomainService!, $migrate: Boolean, $isActive: Boolean!) {
updateAdminDomain(input: {
id: $id,
@@ 747,7 747,7 @@ func (s *Service) DomainCreate(c echo.Context) error {
models.DomainLevelSystem: lt.Translate("System"),
models.DomainLevelUser: lt.Translate("User"),
}
- statusOpt := map[int]string{
+ statusOpt := map[string]string{
models.DomainStatusPending: lt.Translate("Pending"),
models.DomainStatusApproved: lt.Translate("Approved"),
models.DomainStatusError: lt.Translate("Error"),
@@ 793,7 793,7 @@ func (s *Service) DomainCreate(c echo.Context) error {
}
op := gqlclient.NewOperation(
- `mutation AddAdminDomain($name: String!, $lookupName: String!, $orgSlug: String, $level: DomainLevel!, $status: Int!
+ `mutation AddAdminDomain($name: String!, $lookupName: String!, $orgSlug: String, $level: DomainLevel!, $status: DomainStatus!
$service: DomainService!, $migrate: Boolean, $isActive: Boolean!) {
addAdminDomain(input: {
name: $name,
M api/graph/generated.go => api/graph/generated.go +53 -11
@@ 435,6 435,7 @@ type DomainResolver interface {
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)
+ Status(ctx context.Context, obj *models.Domain) (model.DomainStatus, error)
}
type MutationResolver interface {
AddOrganization(ctx context.Context, input model.OrganizationInput) (*models.Organization, error)
@@ 5725,7 5726,7 @@ func (ec *executionContext) _Domain_status(ctx context.Context, field graphql.Co
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
- return obj.Status, nil
+ return ec.resolvers.Domain().Status(rctx, obj)
})
if err != nil {
ec.Error(ctx, err)
@@ 5737,19 5738,19 @@ func (ec *executionContext) _Domain_status(ctx context.Context, field graphql.Co
}
return graphql.Null
}
- res := resTmp.(int)
+ res := resTmp.(model.DomainStatus)
fc.Result = res
- return ec.marshalNInt2int(ctx, field.Selections, res)
+ return ec.marshalNDomainStatus2linksᚋapiᚋgraphᚋmodelᚐDomainStatus(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Domain_status(_ 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 DomainStatus does not have child fields")
},
}
return fc, nil
@@ 21776,7 21777,7 @@ func (ec *executionContext) unmarshalInputAdminDomainInput(ctx context.Context,
it.Level = data
case "status":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("status"))
- data, err := ec.unmarshalNInt2int(ctx, v)
+ data, err := ec.unmarshalNDomainStatus2linksᚋapiᚋgraphᚋmodelᚐDomainStatus(ctx, v)
if err != nil {
return it, err
}
@@ 23084,7 23085,7 @@ func (ec *executionContext) unmarshalInputUpdateAdminDomainInput(ctx context.Con
it.Level = data
case "status":
ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("status"))
- data, err := ec.unmarshalNInt2int(ctx, v)
+ data, err := ec.unmarshalNDomainStatus2linksᚋapiᚋgraphᚋmodelᚐDomainStatus(ctx, v)
if err != nil {
return it, err
}
@@ 24146,10 24147,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 "status":
- out.Values[i] = ec._Domain_status(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_status(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 "isActive":
out.Values[i] = ec._Domain_isActive(ctx, field, obj)
if out.Values[i] == graphql.Null {
@@ 27459,6 27491,16 @@ func (ec *executionContext) marshalNDomainService2linksᚋapiᚋgraphᚋmodelᚐ
return v
}
+func (ec *executionContext) unmarshalNDomainStatus2linksᚋapiᚋgraphᚋmodelᚐDomainStatus(ctx context.Context, v interface{}) (model.DomainStatus, error) {
+ var res model.DomainStatus
+ err := res.UnmarshalGQL(v)
+ return res, graphql.ErrorOnPath(ctx, err)
+}
+
+func (ec *executionContext) marshalNDomainStatus2linksᚋapiᚋgraphᚋmodelᚐDomainStatus(ctx context.Context, sel ast.SelectionSet, v model.DomainStatus) 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)
}
M api/graph/model/models_gen.go => api/graph/model/models_gen.go +45 -2
@@ 72,7 72,7 @@ type AdminDomainInput struct {
OrgSlug *string `json:"orgSlug,omitempty"`
Service DomainService `json:"service"`
Level DomainLevel `json:"level"`
- Status int `json:"status"`
+ Status DomainStatus `json:"status"`
IsActive bool `json:"isActive"`
MigrateLinks *bool `json:"migrateLinks,omitempty"`
}
@@ 378,7 378,7 @@ type UpdateAdminDomainInput struct {
OrgSlug *string `json:"orgSlug,omitempty"`
Service DomainService `json:"service"`
Level DomainLevel `json:"level"`
- Status int `json:"status"`
+ Status DomainStatus `json:"status"`
IsActive bool `json:"isActive"`
MigrateLinks *bool `json:"migrateLinks,omitempty"`
}
@@ 639,3 639,46 @@ func (e *DomainService) UnmarshalGQL(v interface{}) error {
func (e DomainService) MarshalGQL(w io.Writer) {
fmt.Fprint(w, strconv.Quote(e.String()))
}
+
+type DomainStatus string
+
+const (
+ DomainStatusPending DomainStatus = "PENDING"
+ DomainStatusApproved DomainStatus = "APPROVED"
+ DomainStatusError DomainStatus = "ERROR"
+)
+
+var AllDomainStatus = []DomainStatus{
+ DomainStatusPending,
+ DomainStatusApproved,
+ DomainStatusError,
+}
+
+func (e DomainStatus) IsValid() bool {
+ switch e {
+ case DomainStatusPending, DomainStatusApproved, DomainStatusError:
+ return true
+ }
+ return false
+}
+
+func (e DomainStatus) String() string {
+ return string(e)
+}
+
+func (e *DomainStatus) UnmarshalGQL(v interface{}) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+
+ *e = DomainStatus(str)
+ if !e.IsValid() {
+ return fmt.Errorf("%s is not a valid DomainStatus", str)
+ }
+ return nil
+}
+
+func (e DomainStatus) MarshalGQL(w io.Writer) {
+ fmt.Fprint(w, strconv.Quote(e.String()))
+}
M api/graph/schema.graphqls => api/graph/schema.graphqls +8 -3
@@ 74,6 74,11 @@ enum DomainService {
LIST
}
+enum DomainStatus {
+ PENDING
+ APPROVED
+ ERROR
+}
# Considering removing these Null* fields:
@@ 256,7 261,7 @@ type Domain {
orgSlug: NullString! @access(scope: DOMAINS, kind: RO)
service: DomainService!
level: DomainLevel!
- status: Int!
+ status: DomainStatus!
isActive: Boolean! @access(scope: DOMAINS, kind: RO)
createdOn: Time! @access(scope: DOMAINS, kind: RO)
updatedOn: Time! @access(scope: DOMAINS, kind: RO)
@@ 641,7 646,7 @@ input AdminDomainInput {
orgSlug: String
service: DomainService!
level: DomainLevel!
- status: Int!
+ status: DomainStatus!
isActive: Boolean!
migrateLinks: Boolean
}
@@ 653,7 658,7 @@ input UpdateAdminDomainInput {
orgSlug: String
service: DomainService!
level: DomainLevel!
- status: Int!
+ status: DomainStatus!
isActive: Boolean!
migrateLinks: Boolean
}
M api/graph/schema.resolvers.go => api/graph/schema.resolvers.go +10 -7
@@ 39,7 39,7 @@ import (
"golang.org/x/image/draw"
"golang.org/x/net/idna"
"netlandish.com/x/gobwebs"
- "netlandish.com/x/gobwebs-oauth2"
+ oauth2 "netlandish.com/x/gobwebs-oauth2"
gaccounts "netlandish.com/x/gobwebs/accounts"
"netlandish.com/x/gobwebs/crypto"
"netlandish.com/x/gobwebs/database"
@@ 70,6 70,11 @@ func (r *domainResolver) Level(ctx context.Context, obj *models.Domain) (model.D
return model.DomainLevel(obj.Level), nil
}
+// Status is the resolver for the status field.
+func (r *domainResolver) Status(ctx context.Context, obj *models.Domain) (model.DomainStatus, error) {
+ return model.DomainStatus(obj.Status), nil
+}
+
// AddOrganization is the resolver for the addOrganization field.
func (r *mutationResolver) AddOrganization(ctx context.Context, input model.OrganizationInput) (*models.Organization, error) {
tokenUser := oauth2.ForContext(ctx)
@@ 3714,8 3719,7 @@ func (r *mutationResolver) AddAdminDomain(ctx context.Context, input model.Admin
lt.Translate("Invalid level value.")).
WithField("level").
WithCode(valid.ErrValidationCode)
- validator.Expect(input.Status >= models.DomainStatusPending &&
- input.Status <= models.DomainStatusError,
+ validator.Expect(domain.ValidateDomainStatus(string(input.Status)),
lt.Translate("Invalid status value.")).
WithField("status").
WithCode(valid.ErrValidationCode)
@@ 3833,7 3837,7 @@ func (r *mutationResolver) AddAdminDomain(ctx context.Context, input model.Admin
LookupName: host,
Level: string(input.Level),
Service: string(input.Service),
- Status: input.Status,
+ Status: string(input.Status),
IsActive: input.IsActive,
}
if org != nil {
@@ 3889,8 3893,7 @@ func (r *mutationResolver) UpdateAdminDomain(ctx context.Context, input model.Up
lt.Translate("Invalid level value.")).
WithField("level").
WithCode(valid.ErrValidationCode)
- validator.Expect(input.Status >= models.DomainStatusPending &&
- input.Status <= models.DomainStatusError,
+ validator.Expect(domain.ValidateDomainStatus(string(input.Status)),
lt.Translate("Invalid status value.")).
WithField("status").
WithCode(valid.ErrValidationCode)
@@ 4027,7 4030,7 @@ func (r *mutationResolver) UpdateAdminDomain(ctx context.Context, input model.Up
ldomain.LookupName = host
ldomain.Level = string(input.Level)
ldomain.Service = string(input.Service)
- ldomain.Status = input.Status
+ ldomain.Status = string(input.Status)
ldomain.IsActive = input.IsActive
if org != nil {
M domain/logic.go => domain/logic.go +11 -0
@@ 137,3 137,14 @@ func ValidateDomainService(service string) bool {
_, ok := serviceMap[service]
return ok
}
+
+// ValidateDomainStatus is a helper to verify the service given is valid
+func ValidateDomainStatus(status string) bool {
+ statusMap := map[string]bool{
+ models.DomainStatusPending: true,
+ models.DomainStatusApproved: true,
+ models.DomainStatusError: true,
+ }
+ _, ok := statusMap[status]
+ return ok
+}
M migrations/0001_initial.down.sql => migrations/0001_initial.down.sql +1 -0
@@ 34,3 34,4 @@ DROP TABLE IF EXISTS users;
DROP TYPE IF EXISTS domain_level;
DROP TYPE IF EXISTS domain_service;
+DROP TYPE IF EXISTS domain_status;
M migrations/0001_initial.up.sql => migrations/0001_initial.up.sql +10 -1
@@ 30,6 30,15 @@ EXCEPTION
WHEN duplicate_object THEN null;
END $$;
+DO $$ BEGIN
+ CREATE TYPE domain_status AS ENUM (
+ 'PENDING',
+ 'APPROVED',
+ 'ERROR'
+ );
+EXCEPTION
+ WHEN duplicate_object THEN null;
+END $$;
CREATE TABLE users (
@@ 165,7 174,7 @@ CREATE TABLE domains (
org_id INT REFERENCES organizations (id) ON DELETE CASCADE,
level domain_level NOT NULL,
service domain_service NOT NULL,
- status INT DEFAULT 0 NOT NULL,
+ status domain_status DEFAULT 'PENDING' NOT NULL,
is_active BOOLEAN DEFAULT TRUE,
last_action TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
created_on 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', '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 domains (name, lookup_name, org_id, level, service, status) VALUES ('short domain', 'short.domain.org', 1, 'SYSTEM', 'SHORT', 'APPROVED');
+INSERT INTO domains (name, lookup_name, org_id, service, status, level) VALUES ('listing domain', 'list.domain.org', 1, 'LIST', 'APPROVED', '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
@@ 31,11 31,11 @@ const (
const (
// DomainStatusPending ...
- DomainStatusPending int = iota
+ DomainStatusPending string = "PENDING"
// DomainStatusApproved ...
- DomainStatusApproved
+ DomainStatusApproved string = "APPROVED"
// DomainStatusError ...
- DomainStatusError
+ DomainStatusError string = "ERROR"
)
// GetDomains ...
@@ 140,6 140,9 @@ func (d *Domain) Store(ctx context.Context) error {
if d.Service == "" {
d.Service = DomainServiceLinks
}
+ if d.Status == "" {
+ d.Status = DomainStatusPending
+ }
err = sq.
Insert("domains").
Columns("name", "lookup_name", "org_id", "level", "service", "status", "is_active").
M models/models.go => models/models.go +1 -1
@@ 111,7 111,7 @@ type Domain struct {
OrgID sql.NullInt64 `db:"org_id"`
Level string `db:"level"`
Service string `db:"service"`
- Status int `db:"status"`
+ Status string `db:"status"`
IsActive bool `db:"is_active"`
LastAction time.Time `db:"last_action"`
CreatedOn time.Time `db:"created_on"`
M models/schema.sql => models/schema.sql +8 -1
@@ 21,6 21,13 @@ CREATE TYPE domain_service AS ENUM (
'LIST'
);
+CREATE TYPE domain_status AS ENUM (
+ 'PENDING',
+ 'APPROVED',
+ 'ERROR'
+);
+
+
CREATE TABLE users (
id SERIAL PRIMARY KEY,
full_name VARCHAR ( 150 ) NOT NULL,
@@ 154,7 161,7 @@ CREATE TABLE domains (
org_id INT REFERENCES organizations (id) ON DELETE CASCADE,
level domain_level NOT NULL,
service domain_service NOT NULL,
- status INT DEFAULT 0 NOT NULL,
+ status domain_status DEFAULT 'PENDING' NOT NULL,
is_active BOOLEAN DEFAULT TRUE,
last_action TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
created_on TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,