API: basic ACL riggings
This commit is contained in:
parent
cccc0c0ea6
commit
56881ae3e4
|
@ -50,6 +50,7 @@ type ResolverRoot interface {
|
|||
TicketMention() TicketMentionResolver
|
||||
TicketSubscription() TicketSubscriptionResolver
|
||||
Tracker() TrackerResolver
|
||||
TrackerACL() TrackerACLResolver
|
||||
TrackerSubscription() TrackerSubscriptionResolver
|
||||
User() UserResolver
|
||||
UserMention() UserMentionResolver
|
||||
|
@ -345,11 +346,15 @@ type TrackerResolver interface {
|
|||
|
||||
Tickets(ctx context.Context, obj *model.Tracker, cursor *model1.Cursor) (*model.TicketCursor, error)
|
||||
Labels(ctx context.Context, obj *model.Tracker, cursor *model1.Cursor) (*model.LabelCursor, error)
|
||||
Acls(ctx context.Context, obj *model.Tracker, cursor *model1.Cursor) (*model.ACLCursor, error)
|
||||
|
||||
Acls(ctx context.Context, obj *model.Tracker, cursor *model1.Cursor) (*model.ACLCursor, error)
|
||||
Subscription(ctx context.Context, obj *model.Tracker) (*model.TrackerSubscription, error)
|
||||
ACL(ctx context.Context, obj *model.Tracker) (model.ACL, error)
|
||||
}
|
||||
type TrackerACLResolver interface {
|
||||
Tracker(ctx context.Context, obj *model.TrackerACL) (*model.Tracker, error)
|
||||
Entity(ctx context.Context, obj *model.TrackerACL) (model.Entity, error)
|
||||
}
|
||||
type TrackerSubscriptionResolver interface {
|
||||
Tracker(ctx context.Context, obj *model.TrackerSubscription) (*model.Tracker, error)
|
||||
}
|
||||
|
@ -1521,9 +1526,11 @@ type Tracker {
|
|||
tickets(cursor: Cursor): TicketCursor! @access(scope: TICKETS, kind: RO)
|
||||
labels(cursor: Cursor): LabelCursor!
|
||||
|
||||
acls(cursor: Cursor): ACLCursor! @access(scope: ACLS, kind: RO)
|
||||
defaultACLs: DefaultACLs @access(scope: ACLS, kind: RO)
|
||||
|
||||
# Only available to the tracker owner:
|
||||
acls(cursor: Cursor): ACLCursor! @access(scope: ACLS, kind: RO)
|
||||
|
||||
# If the authenticated user is subscribed to this tracker, this is that
|
||||
# subscription.
|
||||
subscription: TrackerSubscription @access(scope: SUBSCRIPTIONS, kind: RO)
|
||||
|
@ -1797,7 +1804,7 @@ type LabelCursor {
|
|||
# back into the same endpoint to retrieve another page. If the cursor is null,
|
||||
# there are no remaining results to return.
|
||||
type ACLCursor {
|
||||
results: [ACL]!
|
||||
results: [TrackerACL]!
|
||||
cursor: Cursor
|
||||
}
|
||||
|
||||
|
@ -2189,9 +2196,9 @@ func (ec *executionContext) _ACLCursor_results(ctx context.Context, field graphq
|
|||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.([]model.ACL)
|
||||
res := resTmp.([]*model.TrackerACL)
|
||||
fc.Result = res
|
||||
return ec.marshalNACL2ᚕgitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐACL(ctx, field.Selections, res)
|
||||
return ec.marshalNTrackerACL2ᚕᚖgitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐTrackerACL(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _ACLCursor_cursor(ctx context.Context, field graphql.CollectedField, obj *model.ACLCursor) (ret graphql.Marshaler) {
|
||||
|
@ -6219,6 +6226,66 @@ func (ec *executionContext) _Tracker_labels(ctx context.Context, field graphql.C
|
|||
return ec.marshalNLabelCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐLabelCursor(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Tracker_defaultACLs(ctx context.Context, field graphql.CollectedField, obj *model.Tracker) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "Tracker",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
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.DefaultACLs, nil
|
||||
}
|
||||
directive1 := func(ctx context.Context) (interface{}, error) {
|
||||
scope, err := ec.unmarshalNAccessScope2gitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "ACLS")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kind, err := ec.unmarshalNAccessKind2gitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋ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.(*model.DefaultACLs); ok {
|
||||
return data, nil
|
||||
}
|
||||
return nil, fmt.Errorf(`unexpected type %T from directive, should be *git.sr.ht/~sircmpwn/todo.sr.ht/api/graph/model.DefaultACLs`, tmp)
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*model.DefaultACLs)
|
||||
fc.Result = res
|
||||
return ec.marshalODefaultACLs2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐDefaultACLs(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Tracker_acls(ctx context.Context, field graphql.CollectedField, obj *model.Tracker) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
|
@ -6289,66 +6356,6 @@ func (ec *executionContext) _Tracker_acls(ctx context.Context, field graphql.Col
|
|||
return ec.marshalNACLCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐACLCursor(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Tracker_defaultACLs(ctx context.Context, field graphql.CollectedField, obj *model.Tracker) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "Tracker",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
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.DefaultACLs, nil
|
||||
}
|
||||
directive1 := func(ctx context.Context) (interface{}, error) {
|
||||
scope, err := ec.unmarshalNAccessScope2gitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "ACLS")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kind, err := ec.unmarshalNAccessKind2gitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋ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.(*model.DefaultACLs); ok {
|
||||
return data, nil
|
||||
}
|
||||
return nil, fmt.Errorf(`unexpected type %T from directive, should be *git.sr.ht/~sircmpwn/todo.sr.ht/api/graph/model.DefaultACLs`, tmp)
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*model.DefaultACLs)
|
||||
fc.Result = res
|
||||
return ec.marshalODefaultACLs2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐDefaultACLs(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Tracker_subscription(ctx context.Context, field graphql.CollectedField, obj *model.Tracker) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
|
@ -6522,14 +6529,14 @@ func (ec *executionContext) _TrackerACL_tracker(ctx context.Context, field graph
|
|||
Object: "TrackerACL",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
IsMethod: true,
|
||||
IsResolver: true,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Tracker, nil
|
||||
return ec.resolvers.TrackerACL().Tracker(rctx, obj)
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
|
@ -6557,15 +6564,15 @@ func (ec *executionContext) _TrackerACL_entity(ctx context.Context, field graphq
|
|||
Object: "TrackerACL",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
IsMethod: true,
|
||||
IsResolver: true,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
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.Entity, nil
|
||||
return ec.resolvers.TrackerACL().Entity(rctx, obj)
|
||||
}
|
||||
directive1 := func(ctx context.Context) (interface{}, error) {
|
||||
scope, err := ec.unmarshalNAccessScope2gitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐAccessScope(ctx, "PROFILE")
|
||||
|
@ -10132,6 +10139,8 @@ func (ec *executionContext) _Tracker(ctx context.Context, sel ast.SelectionSet,
|
|||
}
|
||||
return res
|
||||
})
|
||||
case "defaultACLs":
|
||||
out.Values[i] = ec._Tracker_defaultACLs(ctx, field, obj)
|
||||
case "acls":
|
||||
field := field
|
||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||
|
@ -10146,8 +10155,6 @@ func (ec *executionContext) _Tracker(ctx context.Context, sel ast.SelectionSet,
|
|||
}
|
||||
return res
|
||||
})
|
||||
case "defaultACLs":
|
||||
out.Values[i] = ec._Tracker_defaultACLs(ctx, field, obj)
|
||||
case "subscription":
|
||||
field := field
|
||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||
|
@ -10195,47 +10202,65 @@ func (ec *executionContext) _TrackerACL(ctx context.Context, sel ast.SelectionSe
|
|||
case "id":
|
||||
out.Values[i] = ec._TrackerACL_id(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
}
|
||||
case "created":
|
||||
out.Values[i] = ec._TrackerACL_created(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
}
|
||||
case "tracker":
|
||||
out.Values[i] = ec._TrackerACL_tracker(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
field := field
|
||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._TrackerACL_tracker(ctx, field, obj)
|
||||
if res == graphql.Null {
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
}
|
||||
return res
|
||||
})
|
||||
case "entity":
|
||||
out.Values[i] = ec._TrackerACL_entity(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
field := field
|
||||
out.Concurrently(i, func() (res graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
}
|
||||
}()
|
||||
res = ec._TrackerACL_entity(ctx, field, obj)
|
||||
if res == graphql.Null {
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
}
|
||||
return res
|
||||
})
|
||||
case "browse":
|
||||
out.Values[i] = ec._TrackerACL_browse(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
}
|
||||
case "submit":
|
||||
out.Values[i] = ec._TrackerACL_submit(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
}
|
||||
case "comment":
|
||||
out.Values[i] = ec._TrackerACL_comment(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
}
|
||||
case "edit":
|
||||
out.Values[i] = ec._TrackerACL_edit(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
}
|
||||
case "triage":
|
||||
out.Values[i] = ec._TrackerACL_triage(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
atomic.AddUint32(&invalids, 1)
|
||||
}
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
|
@ -10758,43 +10783,6 @@ func (ec *executionContext) marshalNACL2gitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsr
|
|||
return ec._ACL(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNACL2ᚕgitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐACL(ctx context.Context, sel ast.SelectionSet, v []model.ACL) graphql.Marshaler {
|
||||
ret := make(graphql.Array, len(v))
|
||||
var wg sync.WaitGroup
|
||||
isLen1 := len(v) == 1
|
||||
if !isLen1 {
|
||||
wg.Add(len(v))
|
||||
}
|
||||
for i := range v {
|
||||
i := i
|
||||
fc := &graphql.FieldContext{
|
||||
Index: &i,
|
||||
Result: &v[i],
|
||||
}
|
||||
ctx := graphql.WithFieldContext(ctx, fc)
|
||||
f := func(i int) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = nil
|
||||
}
|
||||
}()
|
||||
if !isLen1 {
|
||||
defer wg.Done()
|
||||
}
|
||||
ret[i] = ec.marshalOACL2gitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐACL(ctx, sel, v[i])
|
||||
}
|
||||
if isLen1 {
|
||||
f(i)
|
||||
} else {
|
||||
go f(i)
|
||||
}
|
||||
|
||||
}
|
||||
wg.Wait()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNACLCursor2gitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐACLCursor(ctx context.Context, sel ast.SelectionSet, v model.ACLCursor) graphql.Marshaler {
|
||||
return ec._ACLCursor(ctx, sel, &v)
|
||||
}
|
||||
|
@ -11282,6 +11270,43 @@ func (ec *executionContext) marshalNTracker2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋtodo
|
|||
return ec._Tracker(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNTrackerACL2ᚕᚖgitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐTrackerACL(ctx context.Context, sel ast.SelectionSet, v []*model.TrackerACL) graphql.Marshaler {
|
||||
ret := make(graphql.Array, len(v))
|
||||
var wg sync.WaitGroup
|
||||
isLen1 := len(v) == 1
|
||||
if !isLen1 {
|
||||
wg.Add(len(v))
|
||||
}
|
||||
for i := range v {
|
||||
i := i
|
||||
fc := &graphql.FieldContext{
|
||||
Index: &i,
|
||||
Result: &v[i],
|
||||
}
|
||||
ctx := graphql.WithFieldContext(ctx, fc)
|
||||
f := func(i int) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = nil
|
||||
}
|
||||
}()
|
||||
if !isLen1 {
|
||||
defer wg.Done()
|
||||
}
|
||||
ret[i] = ec.marshalOTrackerACL2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐTrackerACL(ctx, sel, v[i])
|
||||
}
|
||||
if isLen1 {
|
||||
f(i)
|
||||
} else {
|
||||
go f(i)
|
||||
}
|
||||
|
||||
}
|
||||
wg.Wait()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNTrackerCursor2gitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐTrackerCursor(ctx context.Context, sel ast.SelectionSet, v model.TrackerCursor) graphql.Marshaler {
|
||||
return ec._TrackerCursor(ctx, sel, &v)
|
||||
}
|
||||
|
@ -11723,6 +11748,13 @@ func (ec *executionContext) marshalOTracker2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋtodo
|
|||
return ec._Tracker(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOTrackerACL2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐTrackerACL(ctx context.Context, sel ast.SelectionSet, v *model.TrackerACL) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
return ec._TrackerACL(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalOTrackerCursor2ᚖgitᚗsrᚗhtᚋאsircmpwnᚋtodoᚗsrᚗhtᚋapiᚋgraphᚋmodelᚐTrackerCursor(ctx context.Context, sel ast.SelectionSet, v *model.TrackerCursor) graphql.Marshaler {
|
||||
if v == nil {
|
||||
return graphql.Null
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
|
||||
"git.sr.ht/~sircmpwn/core-go/database"
|
||||
"git.sr.ht/~sircmpwn/core-go/model"
|
||||
)
|
||||
|
||||
type ACL interface {
|
||||
IsACL()
|
||||
}
|
||||
|
||||
type DefaultACL struct {
|
||||
Browse bool `json:"browse"`
|
||||
Submit bool `json:"submit"`
|
||||
Comment bool `json:"comment"`
|
||||
Edit bool `json:"edit"`
|
||||
Triage bool `json:"triage"`
|
||||
}
|
||||
|
||||
func (DefaultACL) IsACL() {}
|
||||
|
||||
type DefaultACLs struct {
|
||||
Anonymous ACL `json:"anonymous"`
|
||||
Submitter ACL `json:"submitter"`
|
||||
LoggedIn ACL `json:"logged_in"`
|
||||
}
|
||||
|
||||
type TrackerACL struct {
|
||||
ID int `json:"id"`
|
||||
Created time.Time `json:"created"`
|
||||
Browse bool `json:"browse"`
|
||||
Submit bool `json:"submit"`
|
||||
Comment bool `json:"comment"`
|
||||
Edit bool `json:"edit"`
|
||||
Triage bool `json:"triage"`
|
||||
|
||||
TrackerID int
|
||||
UserID int
|
||||
|
||||
alias string
|
||||
fields *database.ModelFields
|
||||
}
|
||||
|
||||
func (TrackerACL) IsACL() {}
|
||||
|
||||
func (acl *TrackerACL) As(alias string) *TrackerACL {
|
||||
acl.alias = alias
|
||||
return acl
|
||||
}
|
||||
|
||||
func (acl *TrackerACL) Alias() string {
|
||||
return acl.alias
|
||||
}
|
||||
|
||||
func (acl *TrackerACL) Table() string {
|
||||
return `"user_access"`
|
||||
}
|
||||
|
||||
func (acl *TrackerACL) Fields() *database.ModelFields {
|
||||
if acl.fields != nil {
|
||||
return acl.fields
|
||||
}
|
||||
acl.fields = &database.ModelFields{
|
||||
Fields: []*database.FieldMap{
|
||||
{ "id", "id", &acl.ID },
|
||||
{ "created", "created", &acl.Created },
|
||||
|
||||
// Always fetch:
|
||||
{ "id", "", &acl.ID },
|
||||
{ "user_id", "", &acl.UserID },
|
||||
{ "tracker_id", "", &acl.TrackerID },
|
||||
},
|
||||
}
|
||||
return acl.fields
|
||||
}
|
||||
|
||||
func (acl *TrackerACL) QueryWithCursor(ctx context.Context, runner sq.BaseRunner,
|
||||
q sq.SelectBuilder, cur *model.Cursor) ([]*TrackerACL, *model.Cursor) {
|
||||
var (
|
||||
err error
|
||||
rows *sql.Rows
|
||||
)
|
||||
|
||||
if cur.Next != "" {
|
||||
next, _ := strconv.ParseInt(cur.Next, 10, 64)
|
||||
q = q.Where(database.WithAlias(acl.alias, "id")+"<= ?", next)
|
||||
}
|
||||
q = q.
|
||||
OrderBy(database.WithAlias(acl.alias, "id")).
|
||||
Limit(uint64(cur.Count + 1))
|
||||
|
||||
if rows, err = q.RunWith(runner).QueryContext(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var acls []*TrackerACL
|
||||
for rows.Next() {
|
||||
var acl TrackerACL
|
||||
if err := rows.Scan(database.Scan(ctx, &acl)...); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
acls = append(acls, &acl)
|
||||
}
|
||||
|
||||
if len(acls) > cur.Count {
|
||||
cur = &model.Cursor{
|
||||
Count: cur.Count,
|
||||
Next: strconv.Itoa(acls[len(acls)-1].ID),
|
||||
Search: cur.Search,
|
||||
}
|
||||
acls = acls[:cur.Count]
|
||||
} else {
|
||||
cur = nil
|
||||
}
|
||||
|
||||
return acls, cur
|
||||
}
|
|
@ -11,10 +11,6 @@ import (
|
|||
"git.sr.ht/~sircmpwn/core-go/model"
|
||||
)
|
||||
|
||||
type ACL interface {
|
||||
IsACL()
|
||||
}
|
||||
|
||||
type Entity interface {
|
||||
IsEntity()
|
||||
}
|
||||
|
@ -24,26 +20,10 @@ type EventDetail interface {
|
|||
}
|
||||
|
||||
type ACLCursor struct {
|
||||
Results []ACL `json:"results"`
|
||||
Results []*TrackerACL `json:"results"`
|
||||
Cursor *model.Cursor `json:"cursor"`
|
||||
}
|
||||
|
||||
type DefaultACL struct {
|
||||
Browse bool `json:"browse"`
|
||||
Submit bool `json:"submit"`
|
||||
Comment bool `json:"comment"`
|
||||
Edit bool `json:"edit"`
|
||||
Triage bool `json:"triage"`
|
||||
}
|
||||
|
||||
func (DefaultACL) IsACL() {}
|
||||
|
||||
type DefaultACLs struct {
|
||||
Anonymous ACL `json:"anonymous"`
|
||||
Submitter ACL `json:"submitter"`
|
||||
LoggedIn ACL `json:"logged_in"`
|
||||
}
|
||||
|
||||
type EventCursor struct {
|
||||
Results []*Event `json:"results"`
|
||||
Cursor *model.Cursor `json:"cursor"`
|
||||
|
@ -64,20 +44,6 @@ type TicketCursor struct {
|
|||
Cursor *model.Cursor `json:"cursor"`
|
||||
}
|
||||
|
||||
type TrackerACL struct {
|
||||
ID int `json:"id"`
|
||||
Created time.Time `json:"created"`
|
||||
Tracker *Tracker `json:"tracker"`
|
||||
Entity Entity `json:"entity"`
|
||||
Browse bool `json:"browse"`
|
||||
Submit bool `json:"submit"`
|
||||
Comment bool `json:"comment"`
|
||||
Edit bool `json:"edit"`
|
||||
Triage bool `json:"triage"`
|
||||
}
|
||||
|
||||
func (TrackerACL) IsACL() {}
|
||||
|
||||
type TrackerCursor struct {
|
||||
Results []*Tracker `json:"results"`
|
||||
Cursor *model.Cursor `json:"cursor"`
|
||||
|
|
|
@ -82,9 +82,11 @@ type Tracker {
|
|||
tickets(cursor: Cursor): TicketCursor! @access(scope: TICKETS, kind: RO)
|
||||
labels(cursor: Cursor): LabelCursor!
|
||||
|
||||
acls(cursor: Cursor): ACLCursor! @access(scope: ACLS, kind: RO)
|
||||
defaultACLs: DefaultACLs @access(scope: ACLS, kind: RO)
|
||||
|
||||
# Only available to the tracker owner:
|
||||
acls(cursor: Cursor): ACLCursor! @access(scope: ACLS, kind: RO)
|
||||
|
||||
# If the authenticated user is subscribed to this tracker, this is that
|
||||
# subscription.
|
||||
subscription: TrackerSubscription @access(scope: SUBSCRIPTIONS, kind: RO)
|
||||
|
@ -358,7 +360,7 @@ type LabelCursor {
|
|||
# back into the same endpoint to retrieve another page. If the cursor is null,
|
||||
# there are no remaining results to return.
|
||||
type ACLCursor {
|
||||
results: [ACL]!
|
||||
results: [TrackerACL]!
|
||||
cursor: Cursor
|
||||
}
|
||||
|
||||
|
|
|
@ -422,7 +422,31 @@ func (r *trackerResolver) Labels(ctx context.Context, obj *model.Tracker, cursor
|
|||
}
|
||||
|
||||
func (r *trackerResolver) Acls(ctx context.Context, obj *model.Tracker, cursor *coremodel.Cursor) (*model.ACLCursor, error) {
|
||||
panic(fmt.Errorf("not implemented"))
|
||||
if obj.OwnerID != auth.ForContext(ctx).UserID {
|
||||
return nil, errors.New("Access denied")
|
||||
}
|
||||
|
||||
if cursor == nil {
|
||||
cursor = coremodel.NewCursor(nil)
|
||||
}
|
||||
|
||||
var acls []*model.TrackerACL
|
||||
if err := database.WithTx(ctx, &sql.TxOptions{
|
||||
Isolation: 0,
|
||||
ReadOnly: true,
|
||||
}, func(tx *sql.Tx) error {
|
||||
acl := (&model.TrackerACL{}).As(`ua`)
|
||||
query := database.
|
||||
Select(ctx, acl).
|
||||
From(`user_access ua`).
|
||||
Where(`ua.tracker_id = ?`, obj.ID)
|
||||
acls, cursor = acl.QueryWithCursor(ctx, tx, query, cursor)
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &model.ACLCursor{acls, cursor}, nil
|
||||
}
|
||||
|
||||
func (r *trackerResolver) Subscription(ctx context.Context, obj *model.Tracker) (*model.TrackerSubscription, error) {
|
||||
|
@ -435,6 +459,14 @@ func (r *trackerResolver) ACL(ctx context.Context, obj *model.Tracker) (model.AC
|
|||
panic(fmt.Errorf("not implemented"))
|
||||
}
|
||||
|
||||
func (r *trackerACLResolver) Tracker(ctx context.Context, obj *model.TrackerACL) (*model.Tracker, error) {
|
||||
panic(fmt.Errorf("not implemented"))
|
||||
}
|
||||
|
||||
func (r *trackerACLResolver) Entity(ctx context.Context, obj *model.TrackerACL) (model.Entity, error) {
|
||||
panic(fmt.Errorf("not implemented"))
|
||||
}
|
||||
|
||||
func (r *trackerSubscriptionResolver) Tracker(ctx context.Context, obj *model.TrackerSubscription) (*model.Tracker, error) {
|
||||
return loaders.ForContext(ctx).TrackersByID.Load(obj.TrackerID)
|
||||
}
|
||||
|
@ -525,6 +557,9 @@ func (r *Resolver) TicketSubscription() api.TicketSubscriptionResolver {
|
|||
// Tracker returns api.TrackerResolver implementation.
|
||||
func (r *Resolver) Tracker() api.TrackerResolver { return &trackerResolver{r} }
|
||||
|
||||
// TrackerACL returns api.TrackerACLResolver implementation.
|
||||
func (r *Resolver) TrackerACL() api.TrackerACLResolver { return &trackerACLResolver{r} }
|
||||
|
||||
// TrackerSubscription returns api.TrackerSubscriptionResolver implementation.
|
||||
func (r *Resolver) TrackerSubscription() api.TrackerSubscriptionResolver {
|
||||
return &trackerSubscriptionResolver{r}
|
||||
|
@ -548,6 +583,7 @@ type ticketResolver struct{ *Resolver }
|
|||
type ticketMentionResolver struct{ *Resolver }
|
||||
type ticketSubscriptionResolver struct{ *Resolver }
|
||||
type trackerResolver struct{ *Resolver }
|
||||
type trackerACLResolver struct{ *Resolver }
|
||||
type trackerSubscriptionResolver struct{ *Resolver }
|
||||
type userResolver struct{ *Resolver }
|
||||
type userMentionResolver struct{ *Resolver }
|
||||
|
|
Loading…
Reference in New Issue