M api/graph/generated.go => api/graph/generated.go +52 -9
@@ 480,6 480,8 @@ type OrgLinkResolver interface {
Type(ctx context.Context, obj *models.OrgLink) (model.LinkType, error)
}
type OrganizationResolver interface {
+ OrgType(ctx context.Context, obj *models.Organization) (model.OrgType, error)
+
Image(ctx context.Context, obj *models.Organization) (*graphql.Upload, error)
}
type OrganizationSettingsResolver interface {
@@ 13549,7 13551,7 @@ func (ec *executionContext) _Organization_orgType(ctx context.Context, field gra
}()
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
ctx = rctx // use context from middleware stack in children
- return obj.OrgType, nil
+ return ec.resolvers.Organization().OrgType(rctx, obj)
})
if err != nil {
ec.Error(ctx, err)
@@ 13561,19 13563,19 @@ func (ec *executionContext) _Organization_orgType(ctx context.Context, field gra
}
return graphql.Null
}
- res := resTmp.(int)
+ res := resTmp.(model.OrgType)
fc.Result = res
- return ec.marshalNInt2int(ctx, field.Selections, res)
+ return ec.marshalNOrgType2linksᚋapiᚋgraphᚋmodelᚐOrgType(ctx, field.Selections, res)
}
func (ec *executionContext) fieldContext_Organization_orgType(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
fc = &graphql.FieldContext{
Object: "Organization",
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 OrgType does not have child fields")
},
}
return fc, nil
@@ 25466,10 25468,41 @@ func (ec *executionContext) _Organization(ctx context.Context, sel ast.Selection
atomic.AddUint32(&out.Invalids, 1)
}
case "orgType":
- out.Values[i] = ec._Organization_orgType(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._Organization_orgType(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 "name":
out.Values[i] = ec._Organization_name(ctx, field, obj)
if out.Values[i] == graphql.Null {
@@ 28000,6 28033,16 @@ func (ec *executionContext) marshalNOrgLinkCursor2ᚖlinksᚋapiᚋgraphᚋmodel
return ec._OrgLinkCursor(ctx, sel, v)
}
+func (ec *executionContext) unmarshalNOrgType2linksᚋapiᚋgraphᚋmodelᚐOrgType(ctx context.Context, v interface{}) (model.OrgType, error) {
+ var res model.OrgType
+ err := res.UnmarshalGQL(v)
+ return res, graphql.ErrorOnPath(ctx, err)
+}
+
+func (ec *executionContext) marshalNOrgType2linksᚋapiᚋgraphᚋmodelᚐOrgType(ctx context.Context, sel ast.SelectionSet, v model.OrgType) graphql.Marshaler {
+ return v
+}
+
func (ec *executionContext) marshalNOrganization2linksᚋmodelsᚐOrganization(ctx context.Context, sel ast.SelectionSet, v models.Organization) graphql.Marshaler {
return ec._Organization(ctx, sel, &v)
}
M api/graph/model/models_gen.go => api/graph/model/models_gen.go +41 -0
@@ 809,3 809,44 @@ func (e *MemberPermission) UnmarshalGQL(v interface{}) error {
func (e MemberPermission) MarshalGQL(w io.Writer) {
fmt.Fprint(w, strconv.Quote(e.String()))
}
+
+type OrgType string
+
+const (
+ OrgTypeUser OrgType = "USER"
+ OrgTypeNormal OrgType = "NORMAL"
+)
+
+var AllOrgType = []OrgType{
+ OrgTypeUser,
+ OrgTypeNormal,
+}
+
+func (e OrgType) IsValid() bool {
+ switch e {
+ case OrgTypeUser, OrgTypeNormal:
+ return true
+ }
+ return false
+}
+
+func (e OrgType) String() string {
+ return string(e)
+}
+
+func (e *OrgType) UnmarshalGQL(v interface{}) error {
+ str, ok := v.(string)
+ if !ok {
+ return fmt.Errorf("enums must be strings")
+ }
+
+ *e = OrgType(str)
+ if !e.IsValid() {
+ return fmt.Errorf("%s is not a valid OrgType", str)
+ }
+ return nil
+}
+
+func (e OrgType) MarshalGQL(w io.Writer) {
+ fmt.Fprint(w, strconv.Quote(e.String()))
+}
M api/graph/schema.graphqls => api/graph/schema.graphqls +7 -1
@@ 97,6 97,12 @@ enum MemberPermission {
ADMIN_WRITE
}
+enum OrgType {
+ USER
+ NORMAL
+}
+
+
# Considering removing these Null* fields:
# https://todo.code.netlandish.com/~netlandish/links/75
type NullInt {
@@ 135,7 141,7 @@ type OrganizationSettings {
type Organization {
id: Int!
ownerId: Int! @access(scope: ORGS, kind: RO)
- orgType: Int!
+ orgType: OrgType!
name: String!
slug: String!
image: Upload
M api/graph/schema.resolvers.go => api/graph/schema.resolvers.go +5 -0
@@ 4205,6 4205,11 @@ func (r *orgLinkResolver) Type(ctx context.Context, obj *models.OrgLink) (model.
return model.LinkType(obj.Type), nil
}
+// OrgType is the resolver for the orgType field.
+func (r *organizationResolver) OrgType(ctx context.Context, obj *models.Organization) (model.OrgType, error) {
+ return model.OrgType(obj.OrgType), nil
+}
+
// Image is the resolver for the image field.
func (r *organizationResolver) Image(ctx context.Context, obj *models.Organization) (*graphql.Upload, error) {
panic(fmt.Errorf("not implemented: Image - image"))
M migrations/0001_initial.down.sql => migrations/0001_initial.down.sql +1 -0
@@ 39,3 39,4 @@ DROP TYPE IF EXISTS invoice_status;
DROP TYPE IF EXISTS org_link_visibility;
DROP TYPE IF EXISTS org_link_type;
DROP TYPE IF EXISTS org_user_perm;
+DROP TYPE IF EXISTS org_type;
M migrations/0001_initial.up.sql => migrations/0001_initial.up.sql +10 -1
@@ 80,6 80,15 @@ EXCEPTION
WHEN duplicate_object THEN null;
END $$;
+DO $$ BEGIN
+ CREATE TYPE org_type AS ENUM (
+ 'USER',
+ 'NORMAL'
+ );
+EXCEPTION
+ WHEN duplicate_object THEN null;
+END $$;
+
CREATE TABLE users (
id SERIAL PRIMARY KEY,
@@ 102,7 111,7 @@ CREATE INDEX users_id_idx ON users (id);
CREATE TABLE organizations (
id SERIAL PRIMARY KEY,
owner_id INT REFERENCES users (id) ON DELETE CASCADE NOT NULL,
- org_type INT DEFAULT 0,
+ org_type org_type DEFAULT 'USER',
name VARCHAR ( 150 ) NOT NULL,
slug VARCHAR ( 150 ) UNIQUE NOT NULL,
image VARCHAR(1024) DEFAULT '',
M migrations/test_migration.up.sql => migrations/test_migration.up.sql +1 -1
@@ 3,7 3,7 @@ INSERT INTO users (full_name, password, email, is_verified) VALUES ('test_api_us
INSERT INTO users (full_name, password, email, is_verified, is_superuser) VALUES ('superuser', 'qwerty', 'superuser@api.com', true, true);
INSERT INTO organizations (owner_id, name, slug) VALUES (1, 'personal org', 'personal-org');
-INSERT INTO organizations (owner_id, name, slug, org_type) VALUES (1, 'business org', 'business_org', 1);
+INSERT INTO organizations (owner_id, name, slug, org_type) VALUES (1, 'business org', 'business_org', 'NORMAL');
INSERT INTO organizations (owner_id, name, slug) VALUES (2, 'api test org', 'api-test-org');
M models/models.go => models/models.go +1 -1
@@ 37,7 37,7 @@ type User struct {
type Organization struct {
ID int `db:"id"`
OwnerID int `db:"owner_id"`
- OrgType int `db:"org_type"`
+ OrgType string `db:"org_type"`
Name string `db:"name"`
Slug string `db:"slug"`
Image string `db:"image"`
M models/organization.go => models/organization.go +6 -2
@@ 16,9 16,13 @@ import (
"netlandish.com/x/gobwebs/timezone"
)
+// Organization type is used to define which was created as the "user" org during
+// registration and which is a "normal" org created after registration.
+// USER = Automatically created during registration based off provided username
+// NORMAL = User created additional organization
const (
- OrgTypeUser int = iota
- OrgTypeNormal
+ OrgTypeUser string = "USER"
+ OrgTypeNormal string = "NORMAL"
)
// Billing status, used for org billing setting/metadata
M models/schema.sql => models/schema.sql +7 -2
@@ 51,6 51,12 @@ CREATE TYPE org_link_perm AS ENUM (
'ADMIN_WRITE'
);
+CREATE TYPE org_type AS ENUM (
+ 'USER',
+ 'NORMAL'
+);
+
+
CREATE TABLE users (
id SERIAL PRIMARY KEY,
full_name VARCHAR ( 150 ) NOT NULL,
@@ 72,7 78,7 @@ CREATE INDEX users_id_idx ON users (id);
CREATE TABLE organizations (
id SERIAL PRIMARY KEY,
owner_id INT REFERENCES users (id) ON DELETE CASCADE NOT NULL,
- org_type INT DEFAULT 0,
+ org_type org_type DEFAULT 'USER',
name VARCHAR ( 150 ) NOT NULL,
slug VARCHAR ( 150 ) UNIQUE NOT NULL,
image VARCHAR(1024) DEFAULT '',
@@ 145,7 151,6 @@ CREATE TABLE org_links (
base_url_id INT REFERENCES base_urls (id) ON DELETE CASCADE,
org_id INT REFERENCES organizations (id) ON DELETE CASCADE NOT NULL,
user_id INT REFERENCES users (id) ON DELETE SET NULL,
- visibility INT DEFAULT 0,
visibility org_link_visibility DEFAULT 'PUBLIC',
unread BOOLEAN DEFAULT FALSE NOT NULL,
starred BOOLEAN DEFAULT FALSE NOT NULL,