~netlandish/links

2339a37f3879d5313aa301a5d670510b60fd7e88 — Peter Sanchez a month ago 0afe5b3
More schema cleanup.

References: https://todo.code.netlandish.com/~netlandish/links/60
4 files changed, 421 insertions(+), 360 deletions(-)

M api/api_test.go
M api/graph/generated.go
M api/graph/schema.graphqls
M api/graph/schema.resolvers.go
M api/api_test.go => api/api_test.go +4 -23
@@ 218,21 218,6 @@ func TestDirective(t *testing.T) {
				getLinkShorts(input: {orgSlug: $slug}) {
					result {
						id
					}
			}
		}`)
		op.Var("slug", "personal-org")
		accessToken, err := test.NewAccessTokenTest(ctx, int(user.ID), "SHORTS:RO")
		c.NoError(err)
		client := test.NewClientTest(accessToken)
		err = client.Execute(ctx.Request().Context(), op, &result)
		c.NoError(err)

		op = gqlclient.NewOperation(
			`query GetLinkShorts($slug: String!) {
				getLinkShorts(input: {orgSlug: $slug}) {
					result {
						id
						orgId
						userId
						createdOn


@@ 241,12 226,11 @@ func TestDirective(t *testing.T) {
			}
		}`)
		op.Var("slug", "personal-org")
		accessToken, err = test.NewAccessTokenTest(ctx, int(user.ID), "SHORTS:RO")
		accessToken, err := test.NewAccessTokenTest(ctx, int(user.ID), "SHORTS:RO")
		c.NoError(err)
		client = test.NewClientTest(accessToken)
		client := test.NewClientTest(accessToken)
		err = client.Execute(ctx.Request().Context(), op, &result)
		c.Error(err)
		c.Equal("gqlclient: server failure: Private auth access denied", err.Error())
		c.NoError(err)
	})

	t.Run("list", func(t *testing.T) {


@@ 282,8 266,6 @@ func TestDirective(t *testing.T) {
		err = client.Execute(ctx.Request().Context(), op, &result)
		c.NoError(err)

		// NOTE: now it should fails because we add scope filtering
		// for userId, clicks createdOn and updatedOn
		op = gqlclient.NewOperation(
			`query GetListing($slug: String, $domainId: Int!) {
				getListing(input: {


@@ 308,8 290,7 @@ func TestDirective(t *testing.T) {
		c.NoError(err)
		client = test.NewClientTest(accessToken)
		err = client.Execute(ctx.Request().Context(), op, &result)
		c.Error(err)
		c.Equal("gqlclient: server failure: Private auth access denied", err.Error())
		c.NoError(err)
	})

	t.Run("admin directive", func(t *testing.T) {

M api/graph/generated.go => api/graph/generated.go +376 -296
@@ 4872,28 4872,8 @@ func (ec *executionContext) _BaseURL_createdOn(ctx context.Context, field graphq
		}
	}()
	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 obj.CreatedOn, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
		}

		tmp, err := directive1(rctx)
		if err != nil {
			return nil, graphql.ErrorOnPath(ctx, err)
		}
		if tmp == nil {
			return nil, nil
		}
		if data, ok := tmp.(time.Time); ok {
			return data, nil
		}
		return nil, fmt.Errorf(`unexpected type %T from directive, should be time.Time`, tmp)
		ctx = rctx // use context from middleware stack in children
		return obj.CreatedOn, nil
	})
	if err != nil {
		ec.Error(ctx, err)


@@ 4936,28 4916,8 @@ func (ec *executionContext) _BaseURL_updatedOn(ctx context.Context, field graphq
		}
	}()
	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 obj.UpdatedOn, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
		}

		tmp, err := directive1(rctx)
		if err != nil {
			return nil, graphql.ErrorOnPath(ctx, err)
		}
		if tmp == nil {
			return nil, nil
		}
		if data, ok := tmp.(time.Time); ok {
			return data, nil
		}
		return nil, fmt.Errorf(`unexpected type %T from directive, should be time.Time`, tmp)
		ctx = rctx // use context from middleware stack in children
		return obj.UpdatedOn, nil
	})
	if err != nil {
		ec.Error(ctx, err)


@@ 5608,10 5568,18 @@ func (ec *executionContext) _Domain_isActive(ctx context.Context, field graphql.
			return obj.IsActive, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "DOMAINS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			return ec.directives.Private(ctx, obj, directive0)
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 5672,10 5640,18 @@ func (ec *executionContext) _Domain_createdOn(ctx context.Context, field graphql
			return obj.CreatedOn, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "DOMAINS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 5736,10 5712,18 @@ func (ec *executionContext) _Domain_updatedOn(ctx context.Context, field graphql
			return obj.UpdatedOn, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "DOMAINS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 6480,10 6464,18 @@ func (ec *executionContext) _LinkShort_domainId(ctx context.Context, field graph
			return obj.DomainID, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "SHORTS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 6585,10 6577,18 @@ func (ec *executionContext) _LinkShort_lookupName(ctx context.Context, field gra
			return obj.LookupName, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "SHORTS")
			if err != nil {
				return nil, err
			}
			return ec.directives.Private(ctx, obj, directive0)
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 6649,10 6649,18 @@ func (ec *executionContext) _LinkShort_createdOn(ctx context.Context, field grap
			return obj.CreatedOn, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "SHORTS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 6713,10 6721,18 @@ func (ec *executionContext) _LinkShort_updatedOn(ctx context.Context, field grap
			return obj.UpdatedOn, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "SHORTS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 7118,10 7134,18 @@ func (ec *executionContext) _Listing_isActive(ctx context.Context, field graphql
			return obj.IsActive, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "LISTS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 7182,10 7206,18 @@ func (ec *executionContext) _Listing_isDefault(ctx context.Context, field graphq
			return obj.IsDefault, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "LISTS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			return ec.directives.Private(ctx, obj, directive0)
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 7372,10 7404,18 @@ func (ec *executionContext) _Listing_orgId(ctx context.Context, field graphql.Co
			return obj.OrgID, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "LISTS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 7436,10 7476,18 @@ func (ec *executionContext) _Listing_domainId(ctx context.Context, field graphql
			return obj.DomainID, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "LISTS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 7500,10 7548,18 @@ func (ec *executionContext) _Listing_lookupName(ctx context.Context, field graph
			return obj.LookupName, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "LISTS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 7564,10 7620,18 @@ func (ec *executionContext) _Listing_createdOn(ctx context.Context, field graphq
			return obj.CreatedOn, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "LISTS")
			if err != nil {
				return nil, err
			}
			return ec.directives.Private(ctx, obj, directive0)
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 7628,10 7692,18 @@ func (ec *executionContext) _Listing_updatedOn(ctx context.Context, field graphq
			return obj.UpdatedOn, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "LISTS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 8148,10 8220,18 @@ func (ec *executionContext) _ListingLink_clicks(ctx context.Context, field graph
			return obj.Clicks, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "LISTS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 8212,10 8292,18 @@ func (ec *executionContext) _ListingLink_createdOn(ctx context.Context, field gr
			return obj.CreatedOn, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "LISTS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 8276,10 8364,18 @@ func (ec *executionContext) _ListingLink_updatedOn(ctx context.Context, field gr
			return obj.UpdatedOn, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "LISTS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			return ec.directives.Private(ctx, obj, directive0)
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 12646,44 12742,16 @@ func (ec *executionContext) _OrgLink_createdOn(ctx context.Context, field graphq
		}
	}()
	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 obj.CreatedOn, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "LINKS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)
		if err != nil {
			return nil, graphql.ErrorOnPath(ctx, err)
		}
		if tmp == nil {
			return nil, nil
		}
		if data, ok := tmp.(time.Time); ok {
			return data, nil
		}
		return nil, fmt.Errorf(`unexpected type %T from directive, should be time.Time`, tmp)
	})
	if err != nil {
		ec.Error(ctx, err)
		return graphql.Null
	}
	if resTmp == nil {
		if !graphql.HasFieldError(ctx, fc) {
			ec.Errorf(ctx, "must not be null")
		ctx = rctx // use context from middleware stack in children
		return obj.CreatedOn, nil
	})
	if err != nil {
		ec.Error(ctx, err)
		return graphql.Null
	}
	if resTmp == nil {
		if !graphql.HasFieldError(ctx, fc) {
			ec.Errorf(ctx, "must not be null")
		}
		return graphql.Null
	}


@@ 12718,28 12786,8 @@ func (ec *executionContext) _OrgLink_updatedOn(ctx context.Context, field graphq
		}
	}()
	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 obj.UpdatedOn, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
		}

		tmp, err := directive1(rctx)
		if err != nil {
			return nil, graphql.ErrorOnPath(ctx, err)
		}
		if tmp == nil {
			return nil, nil
		}
		if data, ok := tmp.(time.Time); ok {
			return data, nil
		}
		return nil, fmt.Errorf(`unexpected type %T from directive, should be time.Time`, tmp)
		ctx = rctx // use context from middleware stack in children
		return obj.UpdatedOn, nil
	})
	if err != nil {
		ec.Error(ctx, err)


@@ 12782,36 12830,8 @@ func (ec *executionContext) _OrgLink_baseUrlData(ctx context.Context, field grap
		}
	}()
	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 obj.BaseURLData, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "LINKS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)
		if err != nil {
			return nil, graphql.ErrorOnPath(ctx, err)
		}
		if tmp == nil {
			return nil, nil
		}
		if data, ok := tmp.(models.BaseURLData); ok {
			return data, nil
		}
		return nil, fmt.Errorf(`unexpected type %T from directive, should be links/models.BaseURLData`, tmp)
		ctx = rctx // use context from middleware stack in children
		return obj.BaseURLData, nil
	})
	if err != nil {
		ec.Error(ctx, err)


@@ 13038,10 13058,18 @@ func (ec *executionContext) _Organization_ownerId(ctx context.Context, field gra
			return obj.OwnerID, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "ORGS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			return ec.directives.Private(ctx, obj, directive0)
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 13275,10 13303,18 @@ func (ec *executionContext) _Organization_timezone(ctx context.Context, field gr
			return obj.Timezone, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "ORGS")
			if err != nil {
				return nil, err
			}
			return ec.directives.Private(ctx, obj, directive0)
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 13339,10 13375,18 @@ func (ec *executionContext) _Organization_settings(ctx context.Context, field gr
			return obj.Settings, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "ORGS")
			if err != nil {
				return nil, err
			}
			return ec.directives.Private(ctx, obj, directive0)
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 13407,10 13451,18 @@ func (ec *executionContext) _Organization_isActive(ctx context.Context, field gr
			return obj.IsActive, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "ORGS")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 13466,28 13518,8 @@ func (ec *executionContext) _Organization_createdOn(ctx context.Context, field g
		}
	}()
	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 obj.CreatedOn, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
		}

		tmp, err := directive1(rctx)
		if err != nil {
			return nil, graphql.ErrorOnPath(ctx, err)
		}
		if tmp == nil {
			return nil, nil
		}
		if data, ok := tmp.(time.Time); ok {
			return data, nil
		}
		return nil, fmt.Errorf(`unexpected type %T from directive, should be time.Time`, tmp)
		ctx = rctx // use context from middleware stack in children
		return obj.CreatedOn, nil
	})
	if err != nil {
		ec.Error(ctx, err)


@@ 13530,28 13562,8 @@ func (ec *executionContext) _Organization_updatedOn(ctx context.Context, field g
		}
	}()
	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 obj.UpdatedOn, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
		}

		tmp, err := directive1(rctx)
		if err != nil {
			return nil, graphql.ErrorOnPath(ctx, err)
		}
		if tmp == nil {
			return nil, nil
		}
		if data, ok := tmp.(time.Time); ok {
			return data, nil
		}
		return nil, fmt.Errorf(`unexpected type %T from directive, should be time.Time`, tmp)
		ctx = rctx // use context from middleware stack in children
		return obj.UpdatedOn, nil
	})
	if err != nil {
		ec.Error(ctx, err)


@@ 13599,10 13611,18 @@ func (ec *executionContext) _Organization_ownerName(ctx context.Context, field g
			return obj.OwnerName, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "ORGS")
			if err != nil {
				return nil, err
			}
			return ec.directives.Private(ctx, obj, directive0)
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 14463,10 14483,18 @@ func (ec *executionContext) _Payment_orgId(ctx context.Context, field graphql.Co
			return obj.OrgID, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "BILLING")
			if err != nil {
				return nil, err
			}
			return ec.directives.Private(ctx, obj, directive0)
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 14527,10 14555,18 @@ func (ec *executionContext) _Payment_orgSlug(ctx context.Context, field graphql.
			return obj.OrgSlug, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "BILLING")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 14970,10 15006,18 @@ func (ec *executionContext) _QRCode_hashId(ctx context.Context, field graphql.Co
			return obj.HashID, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "QRCODES")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			return ec.directives.Private(ctx, obj, directive0)
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 15122,10 15166,18 @@ func (ec *executionContext) _QRObject_qrCodeId(ctx context.Context, field graphq
			return obj.QRCodeID, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "QRCODES")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			return ec.directives.Private(ctx, obj, directive0)
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 15186,10 15238,18 @@ func (ec *executionContext) _QRObject_qrHashId(ctx context.Context, field graphq
			return obj.QRHashID, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "QRCODES")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 15250,10 15310,18 @@ func (ec *executionContext) _QRObject_userId(ctx context.Context, field graphql.
			return obj.UserID, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "QRCODES")
			if err != nil {
				return nil, err
			}
			return ec.directives.Private(ctx, obj, directive0)
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 18376,28 18444,8 @@ func (ec *executionContext) _Tag_createdOn(ctx context.Context, field graphql.Co
		}
	}()
	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 obj.CreatedOn, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			}
			return ec.directives.Private(ctx, obj, directive0)
		}

		tmp, err := directive1(rctx)
		if err != nil {
			return nil, graphql.ErrorOnPath(ctx, err)
		}
		if tmp == nil {
			return nil, nil
		}
		if data, ok := tmp.(time.Time); ok {
			return data, nil
		}
		return nil, fmt.Errorf(`unexpected type %T from directive, should be time.Time`, tmp)
		ctx = rctx // use context from middleware stack in children
		return obj.CreatedOn, nil
	})
	if err != nil {
		ec.Error(ctx, err)


@@ 18577,10 18625,18 @@ func (ec *executionContext) _User_createdOn(ctx context.Context, field graphql.C
			return obj.CreatedOn, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "PROFILE")
			if err != nil {
				return nil, err
			}
			return ec.directives.Private(ctx, obj, directive0)
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 18641,10 18697,18 @@ func (ec *executionContext) _User_isActive(ctx context.Context, field graphql.Co
			return obj.IsActive, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "PROFILE")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			return ec.directives.Private(ctx, obj, directive0)
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 18705,10 18769,18 @@ func (ec *executionContext) _User_isLocked(ctx context.Context, field graphql.Co
			return obj.IsLocked, nil
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "PROFILE")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			return ec.directives.Private(ctx, obj, directive0)
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)


@@ 18769,10 18841,18 @@ func (ec *executionContext) _User_lockReadon(ctx context.Context, field graphql.
			return ec.resolvers.User().LockReadon(rctx, obj)
		}
		directive1 := func(ctx context.Context) (interface{}, error) {
			if ec.directives.Private == nil {
				return nil, errors.New("directive private is not implemented")
			scope, err := ec.unmarshalNAccessScope2linksᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "PROFILE")
			if err != nil {
				return nil, err
			}
			kind, err := ec.unmarshalNAccessKind2linksᚋapiᚋgraphᚋmodelᚐAccessKind(ctx, "RO")
			if err != nil {
				return nil, err
			}
			return ec.directives.Private(ctx, obj, directive0)
			if ec.directives.Access == nil {
				return nil, errors.New("directive access is not implemented")
			}
			return ec.directives.Access(ctx, obj, directive0, scope, kind)
		}

		tmp, err := directive1(rctx)

M api/graph/schema.graphqls => api/graph/schema.graphqls +40 -40
@@ 67,10 67,10 @@ type User {
    id: Int!
    name: String!
    email: String!
    createdOn: Time! @private
    isActive: Boolean! @private
    isLocked: Boolean! @private
    lockReadon: String! @private
    createdOn: Time! @access(scope: PROFILE, kind: RO)
    isActive: Boolean! @access(scope: PROFILE, kind: RO)
    isLocked: Boolean! @access(scope: PROFILE, kind: RO)
    lockReadon: String! @access(scope: PROFILE, kind: RO)
}

type BillingSettings {


@@ 83,17 83,17 @@ type OrganizationSettings {

type Organization {
    id: Int!
    ownerId: Int! @private
    ownerId: Int! @access(scope: ORGS, kind: RO)
    orgType: Int!
    name: String!
    slug: String!
    image: Upload
    timezone: String! @private
    settings: OrganizationSettings! @private
    isActive: Boolean! @private
    createdOn: Time! @private
    updatedOn: Time! @private
    ownerName: String! @private
    timezone: String! @access(scope: ORGS, kind: RO)
    settings: OrganizationSettings! @access(scope: ORGS, kind: RO)
    isActive: Boolean! @access(scope: ORGS, kind: RO)
    createdOn: Time!
    updatedOn: Time!
    ownerName: String! @access(scope: ORGS, kind: RO)
}

type Payment {


@@ 105,8 105,8 @@ type Payment {
    amountPaid: Int!
    amountNet: Int! @admin
    paymentFee: Int!
    orgId: Int! @private
    orgSlug: String! @private
    orgId: Int! @access(scope: BILLING, kind: RO)
    orgSlug: String! @access(scope: BILLING, kind: RO)
}

type HTMLMeta {


@@ 128,15 128,15 @@ type BaseURL {
    tags: [Tag]!
    publicReady: Boolean! @internal
    data: BaseURLData!
    createdOn: Time! @private
    updatedOn: Time! @private
    createdOn: Time!
    updatedOn: Time!
}

type Tag {
    id: Int!
    name: String!
    slug: String!
    createdOn: Time! @private
    createdOn: Time!
}

type OrgLink {


@@ 155,9 155,9 @@ type OrgLink {
    tags: [Tag]!
    author: String!
    orgSlug: String! @access(scope: LINKS, kind: RO)
    createdOn: Time! @access(scope: LINKS, kind: RO)
    updatedOn: Time! @private
    baseUrlData: BaseURLData! @access(scope: LINKS, kind: RO)
    createdOn: Time!
    updatedOn: Time!
    baseUrlData: BaseURLData!
}

type LinkShort {


@@ 167,11 167,11 @@ type LinkShort {
    shortCode: String!
    tags: [Tag]!
    userId: Int! @access(scope: SHORTS, kind: RO)
    domainId: Int @private
    domainId: Int @access(scope: SHORTS, kind: RO)
    orgId: Int!
    lookupName: String! @private
    createdOn: Time! @private
    updatedOn: Time! @private
    lookupName: String! @access(scope: SHORTS, kind: RO)
    createdOn: Time! @access(scope: SHORTS, kind: RO)
    updatedOn: Time! @access(scope: SHORTS, kind: RO)
}

type Metadata {


@@ 192,15 192,15 @@ type Listing {
    slug: String!
    image: String!
    metadata: Metadata!
    isActive: Boolean! @private
    isDefault: Boolean! @private
    isActive: Boolean! @access(scope: LISTS, kind: RO)
    isDefault: Boolean! @access(scope: LISTS, kind: RO)
    tags: [Tag]!
    userId: Int! @access(scope: LISTS, kind: RO)
    orgId: Int! @private
    domainId: Int! @private
    lookupName: String! @private
    createdOn: Time! @private
    updatedOn: Time! @private
    orgId: Int! @access(scope: LISTS, kind: RO)
    domainId: Int! @access(scope: LISTS, kind: RO)
    lookupName: String! @access(scope: LISTS, kind: RO)
    createdOn: Time! @access(scope: LISTS, kind: RO)
    updatedOn: Time! @access(scope: LISTS, kind: RO)
}

type ListingLink {


@@ 211,9 211,9 @@ type ListingLink {
    description: String
    userId: Int! @access(scope: LISTS, kind: RO)
    listingId: Int!
    clicks: Int! @private
    createdOn: Time! @private
    updatedOn: Time! @private
    clicks: Int! @access(scope: LISTS, kind: RO)
    createdOn: Time! @access(scope: LISTS, kind: RO)
    updatedOn: Time! @access(scope: LISTS, kind: RO)
}

type Domain {


@@ 225,9 225,9 @@ type Domain {
    service: Int!
    level: Int!
    status: Int!
    isActive: Boolean! @private
    createdOn: Time! @private
    updatedOn: Time! @private
    isActive: Boolean! @access(scope: DOMAINS, kind: RO)
    createdOn: Time! @access(scope: DOMAINS, kind: RO)
    updatedOn: Time! @access(scope: DOMAINS, kind: RO)
}

type PageInfo {


@@ 320,15 320,15 @@ type QRCode {
    codeType: Int!
    url: String!
    imagePath: String!
    hashId: String! @private
    hashId: String! @access(scope: QRCODES, kind: RO)
    createdOn: Time!
    clicks: Int!
}

type QRObject {
    qrCodeId: Int! @private
    qrHashId: String! @private
    userId: Int! @private
    qrCodeId: Int! @access(scope: QRCODES, kind: RO)
    qrHashId: String! @access(scope: QRCODES, kind: RO)
    userId: Int! @access(scope: QRCODES, kind: RO)
    createdOn: Time!
    title: String!
}

M api/graph/schema.resolvers.go => api/graph/schema.resolvers.go +1 -1
@@ 39,7 39,7 @@ import (
	"golang.org/x/image/draw"
	"golang.org/x/net/idna"
	"netlandish.com/x/gobwebs"
	oauth2 "netlandish.com/x/gobwebs-oauth2"
	"netlandish.com/x/gobwebs-oauth2"
	gaccounts "netlandish.com/x/gobwebs/accounts"
	"netlandish.com/x/gobwebs/database"
	"netlandish.com/x/gobwebs/email"