+108
-13
appview/db/label.go
+108
-13
appview/db/label.go
···
13
13
14
14
"github.com/bluesky-social/indigo/atproto/syntax"
15
15
"tangled.sh/tangled.sh/core/api/tangled"
16
+
"tangled.sh/tangled.sh/core/consts"
16
17
)
17
18
18
19
type ConcreteType string
···
77
78
return vt.Type == ConcreteTypeBool
78
79
}
79
80
80
-
func (vt ValueType) IsEnumType() bool {
81
+
func (vt ValueType) IsEnum() bool {
81
82
return len(vt.Enum) > 0
82
83
}
83
84
···
96
97
97
98
Name string
98
99
ValueType ValueType
99
-
Scope syntax.NSID
100
+
Scope []string
100
101
Color *string
101
102
Multiple bool
102
103
Created time.Time
···
113
114
Color: l.Color,
114
115
CreatedAt: l.Created.Format(time.RFC3339),
115
116
Multiple: &l.Multiple,
116
-
Scope: l.Scope.String(),
117
+
Scope: l.Scope,
117
118
ValueType: &vt,
118
119
}
119
120
}
···
139
140
return *ld.Color
140
141
}
141
142
142
-
func LabelDefinitionFromRecord(did, rkey string, record tangled.LabelDefinition) LabelDefinition {
143
+
func LabelDefinitionFromRecord(did, rkey string, record tangled.LabelDefinition) (*LabelDefinition, error) {
143
144
created, err := time.Parse(time.RFC3339, record.CreatedAt)
144
145
if err != nil {
145
146
created = time.Now()
···
155
156
vt = ValueTypeFromRecord(*record.ValueType)
156
157
}
157
158
158
-
return LabelDefinition{
159
+
return &LabelDefinition{
159
160
Did: did,
160
161
Rkey: rkey,
161
162
162
163
Name: record.Name,
163
164
ValueType: vt,
164
-
Scope: syntax.NSID(record.Scope),
165
+
Scope: record.Scope,
165
166
Color: record.Color,
166
167
Multiple: multiple,
167
168
Created: created,
168
-
}
169
+
}, nil
169
170
}
170
171
171
172
func DeleteLabelDefinition(e Execer, filters ...filter) error {
···
184
185
return err
185
186
}
186
187
188
+
// no updating type for now
187
189
func AddLabelDefinition(e Execer, l *LabelDefinition) (int64, error) {
188
190
result, err := e.Exec(
189
191
`insert into label_definitions (
···
210
212
l.ValueType.Type,
211
213
l.ValueType.Format,
212
214
strings.Join(l.ValueType.Enum, ","),
213
-
l.Scope.String(),
215
+
strings.Join(l.Scope, ","),
214
216
l.Color,
215
217
l.Multiple,
216
218
l.Created.Format(time.RFC3339),
···
274
276
275
277
for rows.Next() {
276
278
var labelDefinition LabelDefinition
277
-
var createdAt, enumVariants string
279
+
var createdAt, enumVariants, scopes string
278
280
var color sql.Null[string]
279
281
var multiple int
280
282
···
286
288
&labelDefinition.ValueType.Type,
287
289
&labelDefinition.ValueType.Format,
288
290
&enumVariants,
289
-
&labelDefinition.Scope,
291
+
&scopes,
290
292
&color,
291
293
&multiple,
292
294
&createdAt,
···
309
311
310
312
if enumVariants != "" {
311
313
labelDefinition.ValueType.Enum = strings.Split(enumVariants, ",")
314
+
}
315
+
316
+
for s := range strings.SplitSeq(scopes, ",") {
317
+
labelDefinition.Scope = append(labelDefinition.Scope, s)
312
318
}
313
319
314
320
labelDefinitions = append(labelDefinitions, labelDefinition)
···
631
637
return false
632
638
}
633
639
634
-
func (s *LabelState) GetValSet(l string) set {
635
-
return s.inner[l]
640
+
// go maps behavior in templates make this necessary,
641
+
// indexing a map and getting `set` in return is apparently truthy
642
+
func (s LabelState) ContainsLabelAndVal(l, v string) bool {
643
+
if valset, exists := s.inner[l]; exists {
644
+
if _, exists := valset[v]; exists {
645
+
return true
646
+
}
647
+
}
648
+
649
+
return false
650
+
}
651
+
652
+
func (s LabelState) GetValSet(l string) set {
653
+
if valset, exists := s.inner[l]; exists {
654
+
return valset
655
+
} else {
656
+
return make(set)
657
+
}
636
658
}
637
659
638
660
type LabelApplicationCtx struct {
···
658
680
}
659
681
660
682
func (c *LabelApplicationCtx) ApplyLabelOp(state LabelState, op LabelOp) error {
661
-
def := c.Defs[op.OperandKey]
683
+
def, ok := c.Defs[op.OperandKey]
684
+
if !ok {
685
+
// this def was deleted, but an op exists, so we just skip over the op
686
+
return nil
687
+
}
662
688
663
689
switch op.Operation {
664
690
case LabelOperationAdd:
···
719
745
_ = c.ApplyLabelOp(state, o)
720
746
}
721
747
}
748
+
749
+
// IsInverse checks if one label operation is the inverse of another
750
+
// returns true if one is an add and the other is a delete with the same key and value
751
+
func (op1 LabelOp) IsInverse(op2 LabelOp) bool {
752
+
if op1.OperandKey != op2.OperandKey || op1.OperandValue != op2.OperandValue {
753
+
return false
754
+
}
755
+
756
+
return (op1.Operation == LabelOperationAdd && op2.Operation == LabelOperationDel) ||
757
+
(op1.Operation == LabelOperationDel && op2.Operation == LabelOperationAdd)
758
+
}
759
+
760
+
// removes pairs of label operations that are inverses of each other
761
+
// from the given slice. the function preserves the order of remaining operations.
762
+
func ReduceLabelOps(ops []LabelOp) []LabelOp {
763
+
if len(ops) <= 1 {
764
+
return ops
765
+
}
766
+
767
+
keep := make([]bool, len(ops))
768
+
for i := range keep {
769
+
keep[i] = true
770
+
}
771
+
772
+
for i := range ops {
773
+
if !keep[i] {
774
+
continue
775
+
}
776
+
777
+
for j := i + 1; j < len(ops); j++ {
778
+
if !keep[j] {
779
+
continue
780
+
}
781
+
782
+
if ops[i].IsInverse(ops[j]) {
783
+
keep[i] = false
784
+
keep[j] = false
785
+
break // move to next i since this one is now eliminated
786
+
}
787
+
}
788
+
}
789
+
790
+
// build result slice with only kept operations
791
+
var result []LabelOp
792
+
for i, op := range ops {
793
+
if keep[i] {
794
+
result = append(result, op)
795
+
}
796
+
}
797
+
798
+
return result
799
+
}
800
+
801
+
func DefaultLabelDefs() []string {
802
+
rkeys := []string{
803
+
"wontfix",
804
+
"duplicate",
805
+
"assignee",
806
+
"good-first-issue",
807
+
"documentation",
808
+
}
809
+
810
+
defs := make([]string, len(rkeys))
811
+
for i, r := range rkeys {
812
+
defs[i] = fmt.Sprintf("at://%s/%s/%s", consts.TangledDid, tangled.LabelDefinitionNSID, r)
813
+
}
814
+
815
+
return defs
816
+
}
+7
-14
appview/oauth/handler/handler.go
+7
-14
appview/oauth/handler/handler.go
···
25
25
"tangled.sh/tangled.sh/core/appview/oauth"
26
26
"tangled.sh/tangled.sh/core/appview/oauth/client"
27
27
"tangled.sh/tangled.sh/core/appview/pages"
28
+
"tangled.sh/tangled.sh/core/consts"
28
29
"tangled.sh/tangled.sh/core/idresolver"
29
30
"tangled.sh/tangled.sh/core/rbac"
30
31
"tangled.sh/tangled.sh/core/tid"
···
353
354
return pubKey, nil
354
355
}
355
356
356
-
var (
357
-
tangledDid = "did:plc:wshs7t2adsemcrrd4snkeqli"
358
-
icyDid = "did:plc:hwevmowznbiukdf6uk5dwrrq"
359
-
360
-
defaultSpindle = "spindle.tangled.sh"
361
-
defaultKnot = "knot1.tangled.sh"
362
-
)
363
-
364
357
func (o *OAuthHandler) addToDefaultSpindle(did string) {
365
358
// use the tangled.sh app password to get an accessJwt
366
359
// and create an sh.tangled.spindle.member record with that
···
380
373
}
381
374
382
375
log.Printf("adding %s to default spindle", did)
383
-
session, err := o.createAppPasswordSession(o.config.Core.AppPassword, tangledDid)
376
+
session, err := o.createAppPasswordSession(o.config.Core.AppPassword, consts.TangledDid)
384
377
if err != nil {
385
378
log.Printf("failed to create session: %s", err)
386
379
return
···
389
382
record := tangled.SpindleMember{
390
383
LexiconTypeID: "sh.tangled.spindle.member",
391
384
Subject: did,
392
-
Instance: defaultSpindle,
385
+
Instance: consts.DefaultSpindle,
393
386
CreatedAt: time.Now().Format(time.RFC3339),
394
387
}
395
388
···
411
404
return
412
405
}
413
406
414
-
if slices.Contains(allKnots, defaultKnot) {
407
+
if slices.Contains(allKnots, consts.DefaultKnot) {
415
408
log.Printf("did %s is already a member of the default knot", did)
416
409
return
417
410
}
418
411
419
412
log.Printf("adding %s to default knot", did)
420
-
session, err := o.createAppPasswordSession(o.config.Core.TmpAltAppPassword, icyDid)
413
+
session, err := o.createAppPasswordSession(o.config.Core.TmpAltAppPassword, consts.IcyDid)
421
414
if err != nil {
422
415
log.Printf("failed to create session: %s", err)
423
416
return
···
426
419
record := tangled.KnotMember{
427
420
LexiconTypeID: "sh.tangled.knot.member",
428
421
Subject: did,
429
-
Domain: defaultKnot,
422
+
Domain: consts.DefaultKnot,
430
423
CreatedAt: time.Now().Format(time.RFC3339),
431
424
}
432
425
···
435
428
return
436
429
}
437
430
438
-
if err := o.enforcer.AddKnotMember(defaultKnot, did); err != nil {
431
+
if err := o.enforcer.AddKnotMember(consts.DefaultKnot, did); err != nil {
439
432
log.Printf("failed to set up enforcer rules: %s", err)
440
433
return
441
434
}