From 9772312ca79cab678b08082ed7d7d198b0ec4bc7 Mon Sep 17 00:00:00 2001 From: oppiliappan Date: Tue, 16 Sep 2025 14:46:02 +0100 Subject: [PATCH] appview/consts: init consts package things like TangledDid are now defined in the consts package Signed-off-by: oppiliappan --- appview/db/label.go | 121 +++++++++++++++++++++++++++---- appview/oauth/handler/handler.go | 20 ++--- 2 files changed, 114 insertions(+), 27 deletions(-) diff --git a/appview/db/label.go b/appview/db/label.go index d8a82301..fa1f5590 100644 --- a/appview/db/label.go +++ b/appview/db/label.go @@ -13,6 +13,7 @@ import ( "github.com/bluesky-social/indigo/atproto/syntax" "tangled.sh/tangled.sh/core/api/tangled" + "tangled.sh/tangled.sh/core/consts" ) type ConcreteType string @@ -77,7 +78,7 @@ func (vt ValueType) IsBool() bool { return vt.Type == ConcreteTypeBool } -func (vt ValueType) IsEnumType() bool { +func (vt ValueType) IsEnum() bool { return len(vt.Enum) > 0 } @@ -96,7 +97,7 @@ type LabelDefinition struct { Name string ValueType ValueType - Scope syntax.NSID + Scope []string Color *string Multiple bool Created time.Time @@ -113,7 +114,7 @@ func (l *LabelDefinition) AsRecord() tangled.LabelDefinition { Color: l.Color, CreatedAt: l.Created.Format(time.RFC3339), Multiple: &l.Multiple, - Scope: l.Scope.String(), + Scope: l.Scope, ValueType: &vt, } } @@ -139,7 +140,7 @@ func (ld LabelDefinition) GetColor() string { return *ld.Color } -func LabelDefinitionFromRecord(did, rkey string, record tangled.LabelDefinition) LabelDefinition { +func LabelDefinitionFromRecord(did, rkey string, record tangled.LabelDefinition) (*LabelDefinition, error) { created, err := time.Parse(time.RFC3339, record.CreatedAt) if err != nil { created = time.Now() @@ -155,17 +156,17 @@ func LabelDefinitionFromRecord(did, rkey string, record tangled.LabelDefinition) vt = ValueTypeFromRecord(*record.ValueType) } - return LabelDefinition{ + return &LabelDefinition{ Did: did, Rkey: rkey, Name: record.Name, ValueType: vt, - Scope: syntax.NSID(record.Scope), + Scope: record.Scope, Color: record.Color, Multiple: multiple, Created: created, - } + }, nil } func DeleteLabelDefinition(e Execer, filters ...filter) error { @@ -184,6 +185,7 @@ func DeleteLabelDefinition(e Execer, filters ...filter) error { return err } +// no updating type for now func AddLabelDefinition(e Execer, l *LabelDefinition) (int64, error) { result, err := e.Exec( `insert into label_definitions ( @@ -210,7 +212,7 @@ func AddLabelDefinition(e Execer, l *LabelDefinition) (int64, error) { l.ValueType.Type, l.ValueType.Format, strings.Join(l.ValueType.Enum, ","), - l.Scope.String(), + strings.Join(l.Scope, ","), l.Color, l.Multiple, l.Created.Format(time.RFC3339), @@ -274,7 +276,7 @@ func GetLabelDefinitions(e Execer, filters ...filter) ([]LabelDefinition, error) for rows.Next() { var labelDefinition LabelDefinition - var createdAt, enumVariants string + var createdAt, enumVariants, scopes string var color sql.Null[string] var multiple int @@ -286,7 +288,7 @@ func GetLabelDefinitions(e Execer, filters ...filter) ([]LabelDefinition, error) &labelDefinition.ValueType.Type, &labelDefinition.ValueType.Format, &enumVariants, - &labelDefinition.Scope, + &scopes, &color, &multiple, &createdAt, @@ -311,6 +313,10 @@ func GetLabelDefinitions(e Execer, filters ...filter) ([]LabelDefinition, error) labelDefinition.ValueType.Enum = strings.Split(enumVariants, ",") } + for s := range strings.SplitSeq(scopes, ",") { + labelDefinition.Scope = append(labelDefinition.Scope, s) + } + labelDefinitions = append(labelDefinitions, labelDefinition) } @@ -631,8 +637,24 @@ func (s LabelState) ContainsLabel(l string) bool { return false } -func (s *LabelState) GetValSet(l string) set { - return s.inner[l] +// go maps behavior in templates make this necessary, +// indexing a map and getting `set` in return is apparently truthy +func (s LabelState) ContainsLabelAndVal(l, v string) bool { + if valset, exists := s.inner[l]; exists { + if _, exists := valset[v]; exists { + return true + } + } + + return false +} + +func (s LabelState) GetValSet(l string) set { + if valset, exists := s.inner[l]; exists { + return valset + } else { + return make(set) + } } type LabelApplicationCtx struct { @@ -658,7 +680,11 @@ func NewLabelApplicationCtx(e Execer, filters ...filter) (*LabelApplicationCtx, } func (c *LabelApplicationCtx) ApplyLabelOp(state LabelState, op LabelOp) error { - def := c.Defs[op.OperandKey] + def, ok := c.Defs[op.OperandKey] + if !ok { + // this def was deleted, but an op exists, so we just skip over the op + return nil + } switch op.Operation { case LabelOperationAdd: @@ -719,3 +745,72 @@ func (c *LabelApplicationCtx) ApplyLabelOps(state LabelState, ops []LabelOp) { _ = c.ApplyLabelOp(state, o) } } + +// IsInverse checks if one label operation is the inverse of another +// returns true if one is an add and the other is a delete with the same key and value +func (op1 LabelOp) IsInverse(op2 LabelOp) bool { + if op1.OperandKey != op2.OperandKey || op1.OperandValue != op2.OperandValue { + return false + } + + return (op1.Operation == LabelOperationAdd && op2.Operation == LabelOperationDel) || + (op1.Operation == LabelOperationDel && op2.Operation == LabelOperationAdd) +} + +// removes pairs of label operations that are inverses of each other +// from the given slice. the function preserves the order of remaining operations. +func ReduceLabelOps(ops []LabelOp) []LabelOp { + if len(ops) <= 1 { + return ops + } + + keep := make([]bool, len(ops)) + for i := range keep { + keep[i] = true + } + + for i := range ops { + if !keep[i] { + continue + } + + for j := i + 1; j < len(ops); j++ { + if !keep[j] { + continue + } + + if ops[i].IsInverse(ops[j]) { + keep[i] = false + keep[j] = false + break // move to next i since this one is now eliminated + } + } + } + + // build result slice with only kept operations + var result []LabelOp + for i, op := range ops { + if keep[i] { + result = append(result, op) + } + } + + return result +} + +func DefaultLabelDefs() []string { + rkeys := []string{ + "wontfix", + "duplicate", + "assignee", + "good-first-issue", + "documentation", + } + + defs := make([]string, len(rkeys)) + for i, r := range rkeys { + defs[i] = fmt.Sprintf("at://%s/%s/%s", consts.TangledDid, tangled.LabelDefinitionNSID, r) + } + + return defs +} diff --git a/appview/oauth/handler/handler.go b/appview/oauth/handler/handler.go index c5efa7e3..f94cf2ce 100644 --- a/appview/oauth/handler/handler.go +++ b/appview/oauth/handler/handler.go @@ -353,14 +353,6 @@ func pubKeyFromJwk(jwks string) (jwk.Key, error) { return pubKey, nil } -var ( - tangledDid = "did:plc:wshs7t2adsemcrrd4snkeqli" - icyDid = "did:plc:hwevmowznbiukdf6uk5dwrrq" - - defaultSpindle = "spindle.tangled.sh" - defaultKnot = "knot1.tangled.sh" -) - func (o *OAuthHandler) addToDefaultSpindle(did string) { // use the tangled.sh app password to get an accessJwt // and create an sh.tangled.spindle.member record with that @@ -380,7 +372,7 @@ func (o *OAuthHandler) addToDefaultSpindle(did string) { } log.Printf("adding %s to default spindle", did) - session, err := o.createAppPasswordSession(o.config.Core.AppPassword, tangledDid) + session, err := o.createAppPasswordSession(o.config.Core.AppPassword, consts.TangledDid) if err != nil { log.Printf("failed to create session: %s", err) return @@ -389,7 +381,7 @@ func (o *OAuthHandler) addToDefaultSpindle(did string) { record := tangled.SpindleMember{ LexiconTypeID: "sh.tangled.spindle.member", Subject: did, - Instance: defaultSpindle, + Instance: consts.DefaultSpindle, CreatedAt: time.Now().Format(time.RFC3339), } @@ -411,13 +403,13 @@ func (o *OAuthHandler) addToDefaultKnot(did string) { return } - if slices.Contains(allKnots, defaultKnot) { + if slices.Contains(allKnots, consts.DefaultKnot) { log.Printf("did %s is already a member of the default knot", did) return } log.Printf("adding %s to default knot", did) - session, err := o.createAppPasswordSession(o.config.Core.TmpAltAppPassword, icyDid) + session, err := o.createAppPasswordSession(o.config.Core.TmpAltAppPassword, consts.IcyDid) if err != nil { log.Printf("failed to create session: %s", err) return @@ -426,7 +418,7 @@ func (o *OAuthHandler) addToDefaultKnot(did string) { record := tangled.KnotMember{ LexiconTypeID: "sh.tangled.knot.member", Subject: did, - Domain: defaultKnot, + Domain: consts.DefaultKnot, CreatedAt: time.Now().Format(time.RFC3339), } @@ -435,7 +427,7 @@ func (o *OAuthHandler) addToDefaultKnot(did string) { return } - if err := o.enforcer.AddKnotMember(defaultKnot, did); err != nil { + if err := o.enforcer.AddKnotMember(consts.DefaultKnot, did); err != nil { log.Printf("failed to set up enforcer rules: %s", err) return } -- 2.51.2