Просмотр исходного кода

add address book name &
add share address book

ljw 1 год назад
Родитель
Сommit
8ee93b530d

+ 3 - 1
cmd/apimain.go

@@ -101,7 +101,7 @@ func main() {
101 101
 }
102 102
 
103 103
 func DatabaseAutoUpdate() {
104
-	version := 235
104
+	version := 240
105 105
 
106 106
 	db := global.DB
107 107
 
@@ -165,6 +165,8 @@ func Migrate(version uint) {
165 165
 		&model.ShareRecord{},
166 166
 		&model.AuditConn{},
167 167
 		&model.AuditFile{},
168
+		&model.AddressBookCollection{},
169
+		&model.AddressBookCollectionRule{},
168 170
 	)
169 171
 	if err != nil {
170 172
 		fmt.Println("migrate err :=>", err)

+ 3 - 3
conf/config.yaml

@@ -3,7 +3,7 @@ app:
3 3
   web-client: 1  # 1:启用 0:禁用
4 4
 gin:
5 5
   api-addr: "0.0.0.0:21114"
6
-  mode: "release" #release,debug,test
6
+  mode: "debug" #release,debug,test
7 7
   resources-path: 'resources'  #对外静态文件目录
8 8
   trust-proxy: ""
9 9
 gorm:
@@ -23,11 +23,11 @@ rustdesk:
23 23
   personal: 1
24 24
 logger:
25 25
   path: "./runtime/log.txt"
26
-  level: "warn" #trace,debug,info,warn,error,fatal
26
+  level: "debug" #trace,debug,info,warn,error,fatal
27 27
   report-caller: true
28 28
 proxy:
29 29
   enable: false
30
-  host: ""
30
+  host: "http://127.0.0.1:1080"
31 31
 redis:
32 32
   addr: "127.0.0.1:6379"
33 33
   password: ""

+ 650 - 0
docs/admin/admin_docs.go

@@ -346,6 +346,554 @@ const docTemplateadmin = `{
346 346
                 }
347 347
             }
348 348
         },
349
+        "/admin/address_book_collection/create": {
350
+            "post": {
351
+                "security": [
352
+                    {
353
+                        "token": []
354
+                    }
355
+                ],
356
+                "description": "创建地址簿集合",
357
+                "consumes": [
358
+                    "application/json"
359
+                ],
360
+                "produces": [
361
+                    "application/json"
362
+                ],
363
+                "summary": "创建地址簿集合",
364
+                "parameters": [
365
+                    {
366
+                        "description": "地址簿集合信息",
367
+                        "name": "body",
368
+                        "in": "body",
369
+                        "required": true,
370
+                        "schema": {
371
+                            "$ref": "#/definitions/model.AddressBookCollection"
372
+                        }
373
+                    }
374
+                ],
375
+                "responses": {
376
+                    "200": {
377
+                        "description": "OK",
378
+                        "schema": {
379
+                            "allOf": [
380
+                                {
381
+                                    "$ref": "#/definitions/response.Response"
382
+                                },
383
+                                {
384
+                                    "type": "object",
385
+                                    "properties": {
386
+                                        "data": {
387
+                                            "$ref": "#/definitions/model.AddressBookCollection"
388
+                                        }
389
+                                    }
390
+                                }
391
+                            ]
392
+                        }
393
+                    },
394
+                    "500": {
395
+                        "description": "Internal Server Error",
396
+                        "schema": {
397
+                            "$ref": "#/definitions/response.Response"
398
+                        }
399
+                    }
400
+                }
401
+            }
402
+        },
403
+        "/admin/address_book_collection/delete": {
404
+            "post": {
405
+                "security": [
406
+                    {
407
+                        "token": []
408
+                    }
409
+                ],
410
+                "description": "地址簿集合删除",
411
+                "consumes": [
412
+                    "application/json"
413
+                ],
414
+                "produces": [
415
+                    "application/json"
416
+                ],
417
+                "summary": "地址簿集合删除",
418
+                "parameters": [
419
+                    {
420
+                        "description": "地址簿集合信息",
421
+                        "name": "body",
422
+                        "in": "body",
423
+                        "required": true,
424
+                        "schema": {
425
+                            "$ref": "#/definitions/model.AddressBookCollection"
426
+                        }
427
+                    }
428
+                ],
429
+                "responses": {
430
+                    "200": {
431
+                        "description": "OK",
432
+                        "schema": {
433
+                            "$ref": "#/definitions/response.Response"
434
+                        }
435
+                    },
436
+                    "500": {
437
+                        "description": "Internal Server Error",
438
+                        "schema": {
439
+                            "$ref": "#/definitions/response.Response"
440
+                        }
441
+                    }
442
+                }
443
+            }
444
+        },
445
+        "/admin/address_book_collection/detail/{id}": {
446
+            "get": {
447
+                "security": [
448
+                    {
449
+                        "token": []
450
+                    }
451
+                ],
452
+                "description": "地址簿集合详情",
453
+                "consumes": [
454
+                    "application/json"
455
+                ],
456
+                "produces": [
457
+                    "application/json"
458
+                ],
459
+                "summary": "地址簿集合详情",
460
+                "parameters": [
461
+                    {
462
+                        "type": "integer",
463
+                        "description": "ID",
464
+                        "name": "id",
465
+                        "in": "path",
466
+                        "required": true
467
+                    }
468
+                ],
469
+                "responses": {
470
+                    "200": {
471
+                        "description": "OK",
472
+                        "schema": {
473
+                            "allOf": [
474
+                                {
475
+                                    "$ref": "#/definitions/response.Response"
476
+                                },
477
+                                {
478
+                                    "type": "object",
479
+                                    "properties": {
480
+                                        "data": {
481
+                                            "$ref": "#/definitions/model.AddressBookCollection"
482
+                                        }
483
+                                    }
484
+                                }
485
+                            ]
486
+                        }
487
+                    },
488
+                    "500": {
489
+                        "description": "Internal Server Error",
490
+                        "schema": {
491
+                            "$ref": "#/definitions/response.Response"
492
+                        }
493
+                    }
494
+                }
495
+            }
496
+        },
497
+        "/admin/address_book_collection/list": {
498
+            "get": {
499
+                "security": [
500
+                    {
501
+                        "token": []
502
+                    }
503
+                ],
504
+                "description": "地址簿集合列表",
505
+                "consumes": [
506
+                    "application/json"
507
+                ],
508
+                "produces": [
509
+                    "application/json"
510
+                ],
511
+                "summary": "地址簿集合列表",
512
+                "parameters": [
513
+                    {
514
+                        "type": "integer",
515
+                        "description": "页码",
516
+                        "name": "page",
517
+                        "in": "query"
518
+                    },
519
+                    {
520
+                        "type": "integer",
521
+                        "description": "页大小",
522
+                        "name": "page_size",
523
+                        "in": "query"
524
+                    },
525
+                    {
526
+                        "type": "integer",
527
+                        "description": "是否是我的",
528
+                        "name": "is_my",
529
+                        "in": "query"
530
+                    },
531
+                    {
532
+                        "type": "integer",
533
+                        "description": "用户id",
534
+                        "name": "user_id",
535
+                        "in": "query"
536
+                    }
537
+                ],
538
+                "responses": {
539
+                    "200": {
540
+                        "description": "OK",
541
+                        "schema": {
542
+                            "allOf": [
543
+                                {
544
+                                    "$ref": "#/definitions/response.Response"
545
+                                },
546
+                                {
547
+                                    "type": "object",
548
+                                    "properties": {
549
+                                        "data": {
550
+                                            "$ref": "#/definitions/model.AddressBookCollectionList"
551
+                                        }
552
+                                    }
553
+                                }
554
+                            ]
555
+                        }
556
+                    },
557
+                    "500": {
558
+                        "description": "Internal Server Error",
559
+                        "schema": {
560
+                            "$ref": "#/definitions/response.Response"
561
+                        }
562
+                    }
563
+                }
564
+            }
565
+        },
566
+        "/admin/address_book_collection/update": {
567
+            "post": {
568
+                "security": [
569
+                    {
570
+                        "token": []
571
+                    }
572
+                ],
573
+                "description": "地址簿集合编辑",
574
+                "consumes": [
575
+                    "application/json"
576
+                ],
577
+                "produces": [
578
+                    "application/json"
579
+                ],
580
+                "summary": "地址簿集合编辑",
581
+                "parameters": [
582
+                    {
583
+                        "description": "地址簿集合信息",
584
+                        "name": "body",
585
+                        "in": "body",
586
+                        "required": true,
587
+                        "schema": {
588
+                            "$ref": "#/definitions/model.AddressBookCollection"
589
+                        }
590
+                    }
591
+                ],
592
+                "responses": {
593
+                    "200": {
594
+                        "description": "OK",
595
+                        "schema": {
596
+                            "allOf": [
597
+                                {
598
+                                    "$ref": "#/definitions/response.Response"
599
+                                },
600
+                                {
601
+                                    "type": "object",
602
+                                    "properties": {
603
+                                        "data": {
604
+                                            "$ref": "#/definitions/model.AddressBookCollection"
605
+                                        }
606
+                                    }
607
+                                }
608
+                            ]
609
+                        }
610
+                    },
611
+                    "500": {
612
+                        "description": "Internal Server Error",
613
+                        "schema": {
614
+                            "$ref": "#/definitions/response.Response"
615
+                        }
616
+                    }
617
+                }
618
+            }
619
+        },
620
+        "/admin/address_book_collection_rule/create": {
621
+            "post": {
622
+                "security": [
623
+                    {
624
+                        "token": []
625
+                    }
626
+                ],
627
+                "description": "创建地址簿集合规则",
628
+                "consumes": [
629
+                    "application/json"
630
+                ],
631
+                "produces": [
632
+                    "application/json"
633
+                ],
634
+                "summary": "创建地址簿集合规则",
635
+                "parameters": [
636
+                    {
637
+                        "description": "地址簿集合规则信息",
638
+                        "name": "body",
639
+                        "in": "body",
640
+                        "required": true,
641
+                        "schema": {
642
+                            "$ref": "#/definitions/model.AddressBookCollectionRule"
643
+                        }
644
+                    }
645
+                ],
646
+                "responses": {
647
+                    "200": {
648
+                        "description": "OK",
649
+                        "schema": {
650
+                            "allOf": [
651
+                                {
652
+                                    "$ref": "#/definitions/response.Response"
653
+                                },
654
+                                {
655
+                                    "type": "object",
656
+                                    "properties": {
657
+                                        "data": {
658
+                                            "$ref": "#/definitions/model.AddressBookCollection"
659
+                                        }
660
+                                    }
661
+                                }
662
+                            ]
663
+                        }
664
+                    },
665
+                    "500": {
666
+                        "description": "Internal Server Error",
667
+                        "schema": {
668
+                            "$ref": "#/definitions/response.Response"
669
+                        }
670
+                    }
671
+                }
672
+            }
673
+        },
674
+        "/admin/address_book_collection_rule/delete": {
675
+            "post": {
676
+                "security": [
677
+                    {
678
+                        "token": []
679
+                    }
680
+                ],
681
+                "description": "地址簿集合规则删除",
682
+                "consumes": [
683
+                    "application/json"
684
+                ],
685
+                "produces": [
686
+                    "application/json"
687
+                ],
688
+                "summary": "地址簿集合规则删除",
689
+                "parameters": [
690
+                    {
691
+                        "description": "地址簿集合规则信息",
692
+                        "name": "body",
693
+                        "in": "body",
694
+                        "required": true,
695
+                        "schema": {
696
+                            "$ref": "#/definitions/model.AddressBookCollectionRule"
697
+                        }
698
+                    }
699
+                ],
700
+                "responses": {
701
+                    "200": {
702
+                        "description": "OK",
703
+                        "schema": {
704
+                            "$ref": "#/definitions/response.Response"
705
+                        }
706
+                    },
707
+                    "500": {
708
+                        "description": "Internal Server Error",
709
+                        "schema": {
710
+                            "$ref": "#/definitions/response.Response"
711
+                        }
712
+                    }
713
+                }
714
+            }
715
+        },
716
+        "/admin/address_book_collection_rule/detail/{id}": {
717
+            "get": {
718
+                "security": [
719
+                    {
720
+                        "token": []
721
+                    }
722
+                ],
723
+                "description": "地址簿集合规则详情",
724
+                "consumes": [
725
+                    "application/json"
726
+                ],
727
+                "produces": [
728
+                    "application/json"
729
+                ],
730
+                "summary": "地址簿集合规则详情",
731
+                "parameters": [
732
+                    {
733
+                        "type": "integer",
734
+                        "description": "ID",
735
+                        "name": "id",
736
+                        "in": "path",
737
+                        "required": true
738
+                    }
739
+                ],
740
+                "responses": {
741
+                    "200": {
742
+                        "description": "OK",
743
+                        "schema": {
744
+                            "allOf": [
745
+                                {
746
+                                    "$ref": "#/definitions/response.Response"
747
+                                },
748
+                                {
749
+                                    "type": "object",
750
+                                    "properties": {
751
+                                        "data": {
752
+                                            "$ref": "#/definitions/model.AddressBookCollectionRule"
753
+                                        }
754
+                                    }
755
+                                }
756
+                            ]
757
+                        }
758
+                    },
759
+                    "500": {
760
+                        "description": "Internal Server Error",
761
+                        "schema": {
762
+                            "$ref": "#/definitions/response.Response"
763
+                        }
764
+                    }
765
+                }
766
+            }
767
+        },
768
+        "/admin/address_book_collection_rule/list": {
769
+            "get": {
770
+                "security": [
771
+                    {
772
+                        "token": []
773
+                    }
774
+                ],
775
+                "description": "地址簿集合规则列表",
776
+                "consumes": [
777
+                    "application/json"
778
+                ],
779
+                "produces": [
780
+                    "application/json"
781
+                ],
782
+                "summary": "地址簿集合规则列表",
783
+                "parameters": [
784
+                    {
785
+                        "type": "integer",
786
+                        "description": "页码",
787
+                        "name": "page",
788
+                        "in": "query"
789
+                    },
790
+                    {
791
+                        "type": "integer",
792
+                        "description": "页大小",
793
+                        "name": "page_size",
794
+                        "in": "query"
795
+                    },
796
+                    {
797
+                        "type": "integer",
798
+                        "description": "是否是我的",
799
+                        "name": "is_my",
800
+                        "in": "query"
801
+                    },
802
+                    {
803
+                        "type": "integer",
804
+                        "description": "用户id",
805
+                        "name": "user_id",
806
+                        "in": "query"
807
+                    },
808
+                    {
809
+                        "type": "integer",
810
+                        "description": "地址簿集合id",
811
+                        "name": "collection_id",
812
+                        "in": "query"
813
+                    }
814
+                ],
815
+                "responses": {
816
+                    "200": {
817
+                        "description": "OK",
818
+                        "schema": {
819
+                            "allOf": [
820
+                                {
821
+                                    "$ref": "#/definitions/response.Response"
822
+                                },
823
+                                {
824
+                                    "type": "object",
825
+                                    "properties": {
826
+                                        "data": {
827
+                                            "$ref": "#/definitions/model.AddressBookCollectionList"
828
+                                        }
829
+                                    }
830
+                                }
831
+                            ]
832
+                        }
833
+                    },
834
+                    "500": {
835
+                        "description": "Internal Server Error",
836
+                        "schema": {
837
+                            "$ref": "#/definitions/response.Response"
838
+                        }
839
+                    }
840
+                }
841
+            }
842
+        },
843
+        "/admin/address_book_collection_rule/update": {
844
+            "post": {
845
+                "security": [
846
+                    {
847
+                        "token": []
848
+                    }
849
+                ],
850
+                "description": "地址簿集合规则编辑",
851
+                "consumes": [
852
+                    "application/json"
853
+                ],
854
+                "produces": [
855
+                    "application/json"
856
+                ],
857
+                "summary": "地址簿集合规则编辑",
858
+                "parameters": [
859
+                    {
860
+                        "description": "地址簿集合规则信息",
861
+                        "name": "body",
862
+                        "in": "body",
863
+                        "required": true,
864
+                        "schema": {
865
+                            "$ref": "#/definitions/model.AddressBookCollectionRule"
866
+                        }
867
+                    }
868
+                ],
869
+                "responses": {
870
+                    "200": {
871
+                        "description": "OK",
872
+                        "schema": {
873
+                            "allOf": [
874
+                                {
875
+                                    "$ref": "#/definitions/response.Response"
876
+                                },
877
+                                {
878
+                                    "type": "object",
879
+                                    "properties": {
880
+                                        "data": {
881
+                                            "$ref": "#/definitions/model.AddressBookCollection"
882
+                                        }
883
+                                    }
884
+                                }
885
+                            ]
886
+                        }
887
+                    },
888
+                    "500": {
889
+                        "description": "Internal Server Error",
890
+                        "schema": {
891
+                            "$ref": "#/definitions/response.Response"
892
+                        }
893
+                    }
894
+                }
895
+            }
896
+        },
349 897
         "/admin/app-config": {
350 898
             "get": {
351 899
                 "security": [
@@ -2480,6 +3028,9 @@ const docTemplateadmin = `{
2480 3028
                 "alias": {
2481 3029
                     "type": "string"
2482 3030
                 },
3031
+                "collection_id": {
3032
+                    "type": "integer"
3033
+                },
2483 3034
                 "forceAlwaysRelay": {
2484 3035
                     "type": "boolean"
2485 3036
                 },
@@ -2701,6 +3252,9 @@ const docTemplateadmin = `{
2701 3252
                 "name"
2702 3253
             ],
2703 3254
             "properties": {
3255
+                "collection_id": {
3256
+                    "type": "integer"
3257
+                },
2704 3258
                 "color": {
2705 3259
                     "type": "integer"
2706 3260
                 },
@@ -2788,6 +3342,12 @@ const docTemplateadmin = `{
2788 3342
                 "alias": {
2789 3343
                     "type": "string"
2790 3344
                 },
3345
+                "collection": {
3346
+                    "$ref": "#/definitions/model.AddressBookCollection"
3347
+                },
3348
+                "collection_id": {
3349
+                    "type": "integer"
3350
+                },
2791 3351
                 "created_at": {
2792 3352
                     "type": "string"
2793 3353
                 },
@@ -2844,6 +3404,90 @@ const docTemplateadmin = `{
2844 3404
                 }
2845 3405
             }
2846 3406
         },
3407
+        "model.AddressBookCollection": {
3408
+            "type": "object",
3409
+            "required": [
3410
+                "name"
3411
+            ],
3412
+            "properties": {
3413
+                "created_at": {
3414
+                    "type": "string"
3415
+                },
3416
+                "id": {
3417
+                    "type": "integer"
3418
+                },
3419
+                "name": {
3420
+                    "type": "string"
3421
+                },
3422
+                "updated_at": {
3423
+                    "type": "string"
3424
+                },
3425
+                "user_id": {
3426
+                    "type": "integer"
3427
+                }
3428
+            }
3429
+        },
3430
+        "model.AddressBookCollectionList": {
3431
+            "type": "object",
3432
+            "properties": {
3433
+                "list": {
3434
+                    "type": "array",
3435
+                    "items": {
3436
+                        "$ref": "#/definitions/model.AddressBookCollection"
3437
+                    }
3438
+                },
3439
+                "page": {
3440
+                    "type": "integer"
3441
+                },
3442
+                "page_size": {
3443
+                    "type": "integer"
3444
+                },
3445
+                "total": {
3446
+                    "type": "integer"
3447
+                }
3448
+            }
3449
+        },
3450
+        "model.AddressBookCollectionRule": {
3451
+            "type": "object",
3452
+            "required": [
3453
+                "collection_id",
3454
+                "rule",
3455
+                "to_id",
3456
+                "type"
3457
+            ],
3458
+            "properties": {
3459
+                "collection_id": {
3460
+                    "type": "integer"
3461
+                },
3462
+                "created_at": {
3463
+                    "type": "string"
3464
+                },
3465
+                "id": {
3466
+                    "type": "integer"
3467
+                },
3468
+                "rule": {
3469
+                    "description": "0: 无 1: 读 2: 读写  3: 完全控制",
3470
+                    "type": "integer",
3471
+                    "maximum": 3,
3472
+                    "minimum": 1
3473
+                },
3474
+                "to_id": {
3475
+                    "type": "integer"
3476
+                },
3477
+                "type": {
3478
+                    "description": "1: 个人 2: 群组",
3479
+                    "type": "integer",
3480
+                    "maximum": 2,
3481
+                    "minimum": 1
3482
+                },
3483
+                "updated_at": {
3484
+                    "type": "string"
3485
+                },
3486
+                "user_id": {
3487
+                    "type": "integer"
3488
+                }
3489
+            }
3490
+        },
2847 3491
         "model.AddressBookList": {
2848 3492
             "type": "object",
2849 3493
             "properties": {
@@ -3221,6 +3865,12 @@ const docTemplateadmin = `{
3221 3865
         "model.Tag": {
3222 3866
             "type": "object",
3223 3867
             "properties": {
3868
+                "collection": {
3869
+                    "$ref": "#/definitions/model.AddressBookCollection"
3870
+                },
3871
+                "collection_id": {
3872
+                    "type": "integer"
3873
+                },
3224 3874
                 "color": {
3225 3875
                     "description": "color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba",
3226 3876
                     "type": "integer"

+ 650 - 0
docs/admin/admin_swagger.json

@@ -339,6 +339,554 @@
339 339
                 }
340 340
             }
341 341
         },
342
+        "/admin/address_book_collection/create": {
343
+            "post": {
344
+                "security": [
345
+                    {
346
+                        "token": []
347
+                    }
348
+                ],
349
+                "description": "创建地址簿集合",
350
+                "consumes": [
351
+                    "application/json"
352
+                ],
353
+                "produces": [
354
+                    "application/json"
355
+                ],
356
+                "summary": "创建地址簿集合",
357
+                "parameters": [
358
+                    {
359
+                        "description": "地址簿集合信息",
360
+                        "name": "body",
361
+                        "in": "body",
362
+                        "required": true,
363
+                        "schema": {
364
+                            "$ref": "#/definitions/model.AddressBookCollection"
365
+                        }
366
+                    }
367
+                ],
368
+                "responses": {
369
+                    "200": {
370
+                        "description": "OK",
371
+                        "schema": {
372
+                            "allOf": [
373
+                                {
374
+                                    "$ref": "#/definitions/response.Response"
375
+                                },
376
+                                {
377
+                                    "type": "object",
378
+                                    "properties": {
379
+                                        "data": {
380
+                                            "$ref": "#/definitions/model.AddressBookCollection"
381
+                                        }
382
+                                    }
383
+                                }
384
+                            ]
385
+                        }
386
+                    },
387
+                    "500": {
388
+                        "description": "Internal Server Error",
389
+                        "schema": {
390
+                            "$ref": "#/definitions/response.Response"
391
+                        }
392
+                    }
393
+                }
394
+            }
395
+        },
396
+        "/admin/address_book_collection/delete": {
397
+            "post": {
398
+                "security": [
399
+                    {
400
+                        "token": []
401
+                    }
402
+                ],
403
+                "description": "地址簿集合删除",
404
+                "consumes": [
405
+                    "application/json"
406
+                ],
407
+                "produces": [
408
+                    "application/json"
409
+                ],
410
+                "summary": "地址簿集合删除",
411
+                "parameters": [
412
+                    {
413
+                        "description": "地址簿集合信息",
414
+                        "name": "body",
415
+                        "in": "body",
416
+                        "required": true,
417
+                        "schema": {
418
+                            "$ref": "#/definitions/model.AddressBookCollection"
419
+                        }
420
+                    }
421
+                ],
422
+                "responses": {
423
+                    "200": {
424
+                        "description": "OK",
425
+                        "schema": {
426
+                            "$ref": "#/definitions/response.Response"
427
+                        }
428
+                    },
429
+                    "500": {
430
+                        "description": "Internal Server Error",
431
+                        "schema": {
432
+                            "$ref": "#/definitions/response.Response"
433
+                        }
434
+                    }
435
+                }
436
+            }
437
+        },
438
+        "/admin/address_book_collection/detail/{id}": {
439
+            "get": {
440
+                "security": [
441
+                    {
442
+                        "token": []
443
+                    }
444
+                ],
445
+                "description": "地址簿集合详情",
446
+                "consumes": [
447
+                    "application/json"
448
+                ],
449
+                "produces": [
450
+                    "application/json"
451
+                ],
452
+                "summary": "地址簿集合详情",
453
+                "parameters": [
454
+                    {
455
+                        "type": "integer",
456
+                        "description": "ID",
457
+                        "name": "id",
458
+                        "in": "path",
459
+                        "required": true
460
+                    }
461
+                ],
462
+                "responses": {
463
+                    "200": {
464
+                        "description": "OK",
465
+                        "schema": {
466
+                            "allOf": [
467
+                                {
468
+                                    "$ref": "#/definitions/response.Response"
469
+                                },
470
+                                {
471
+                                    "type": "object",
472
+                                    "properties": {
473
+                                        "data": {
474
+                                            "$ref": "#/definitions/model.AddressBookCollection"
475
+                                        }
476
+                                    }
477
+                                }
478
+                            ]
479
+                        }
480
+                    },
481
+                    "500": {
482
+                        "description": "Internal Server Error",
483
+                        "schema": {
484
+                            "$ref": "#/definitions/response.Response"
485
+                        }
486
+                    }
487
+                }
488
+            }
489
+        },
490
+        "/admin/address_book_collection/list": {
491
+            "get": {
492
+                "security": [
493
+                    {
494
+                        "token": []
495
+                    }
496
+                ],
497
+                "description": "地址簿集合列表",
498
+                "consumes": [
499
+                    "application/json"
500
+                ],
501
+                "produces": [
502
+                    "application/json"
503
+                ],
504
+                "summary": "地址簿集合列表",
505
+                "parameters": [
506
+                    {
507
+                        "type": "integer",
508
+                        "description": "页码",
509
+                        "name": "page",
510
+                        "in": "query"
511
+                    },
512
+                    {
513
+                        "type": "integer",
514
+                        "description": "页大小",
515
+                        "name": "page_size",
516
+                        "in": "query"
517
+                    },
518
+                    {
519
+                        "type": "integer",
520
+                        "description": "是否是我的",
521
+                        "name": "is_my",
522
+                        "in": "query"
523
+                    },
524
+                    {
525
+                        "type": "integer",
526
+                        "description": "用户id",
527
+                        "name": "user_id",
528
+                        "in": "query"
529
+                    }
530
+                ],
531
+                "responses": {
532
+                    "200": {
533
+                        "description": "OK",
534
+                        "schema": {
535
+                            "allOf": [
536
+                                {
537
+                                    "$ref": "#/definitions/response.Response"
538
+                                },
539
+                                {
540
+                                    "type": "object",
541
+                                    "properties": {
542
+                                        "data": {
543
+                                            "$ref": "#/definitions/model.AddressBookCollectionList"
544
+                                        }
545
+                                    }
546
+                                }
547
+                            ]
548
+                        }
549
+                    },
550
+                    "500": {
551
+                        "description": "Internal Server Error",
552
+                        "schema": {
553
+                            "$ref": "#/definitions/response.Response"
554
+                        }
555
+                    }
556
+                }
557
+            }
558
+        },
559
+        "/admin/address_book_collection/update": {
560
+            "post": {
561
+                "security": [
562
+                    {
563
+                        "token": []
564
+                    }
565
+                ],
566
+                "description": "地址簿集合编辑",
567
+                "consumes": [
568
+                    "application/json"
569
+                ],
570
+                "produces": [
571
+                    "application/json"
572
+                ],
573
+                "summary": "地址簿集合编辑",
574
+                "parameters": [
575
+                    {
576
+                        "description": "地址簿集合信息",
577
+                        "name": "body",
578
+                        "in": "body",
579
+                        "required": true,
580
+                        "schema": {
581
+                            "$ref": "#/definitions/model.AddressBookCollection"
582
+                        }
583
+                    }
584
+                ],
585
+                "responses": {
586
+                    "200": {
587
+                        "description": "OK",
588
+                        "schema": {
589
+                            "allOf": [
590
+                                {
591
+                                    "$ref": "#/definitions/response.Response"
592
+                                },
593
+                                {
594
+                                    "type": "object",
595
+                                    "properties": {
596
+                                        "data": {
597
+                                            "$ref": "#/definitions/model.AddressBookCollection"
598
+                                        }
599
+                                    }
600
+                                }
601
+                            ]
602
+                        }
603
+                    },
604
+                    "500": {
605
+                        "description": "Internal Server Error",
606
+                        "schema": {
607
+                            "$ref": "#/definitions/response.Response"
608
+                        }
609
+                    }
610
+                }
611
+            }
612
+        },
613
+        "/admin/address_book_collection_rule/create": {
614
+            "post": {
615
+                "security": [
616
+                    {
617
+                        "token": []
618
+                    }
619
+                ],
620
+                "description": "创建地址簿集合规则",
621
+                "consumes": [
622
+                    "application/json"
623
+                ],
624
+                "produces": [
625
+                    "application/json"
626
+                ],
627
+                "summary": "创建地址簿集合规则",
628
+                "parameters": [
629
+                    {
630
+                        "description": "地址簿集合规则信息",
631
+                        "name": "body",
632
+                        "in": "body",
633
+                        "required": true,
634
+                        "schema": {
635
+                            "$ref": "#/definitions/model.AddressBookCollectionRule"
636
+                        }
637
+                    }
638
+                ],
639
+                "responses": {
640
+                    "200": {
641
+                        "description": "OK",
642
+                        "schema": {
643
+                            "allOf": [
644
+                                {
645
+                                    "$ref": "#/definitions/response.Response"
646
+                                },
647
+                                {
648
+                                    "type": "object",
649
+                                    "properties": {
650
+                                        "data": {
651
+                                            "$ref": "#/definitions/model.AddressBookCollection"
652
+                                        }
653
+                                    }
654
+                                }
655
+                            ]
656
+                        }
657
+                    },
658
+                    "500": {
659
+                        "description": "Internal Server Error",
660
+                        "schema": {
661
+                            "$ref": "#/definitions/response.Response"
662
+                        }
663
+                    }
664
+                }
665
+            }
666
+        },
667
+        "/admin/address_book_collection_rule/delete": {
668
+            "post": {
669
+                "security": [
670
+                    {
671
+                        "token": []
672
+                    }
673
+                ],
674
+                "description": "地址簿集合规则删除",
675
+                "consumes": [
676
+                    "application/json"
677
+                ],
678
+                "produces": [
679
+                    "application/json"
680
+                ],
681
+                "summary": "地址簿集合规则删除",
682
+                "parameters": [
683
+                    {
684
+                        "description": "地址簿集合规则信息",
685
+                        "name": "body",
686
+                        "in": "body",
687
+                        "required": true,
688
+                        "schema": {
689
+                            "$ref": "#/definitions/model.AddressBookCollectionRule"
690
+                        }
691
+                    }
692
+                ],
693
+                "responses": {
694
+                    "200": {
695
+                        "description": "OK",
696
+                        "schema": {
697
+                            "$ref": "#/definitions/response.Response"
698
+                        }
699
+                    },
700
+                    "500": {
701
+                        "description": "Internal Server Error",
702
+                        "schema": {
703
+                            "$ref": "#/definitions/response.Response"
704
+                        }
705
+                    }
706
+                }
707
+            }
708
+        },
709
+        "/admin/address_book_collection_rule/detail/{id}": {
710
+            "get": {
711
+                "security": [
712
+                    {
713
+                        "token": []
714
+                    }
715
+                ],
716
+                "description": "地址簿集合规则详情",
717
+                "consumes": [
718
+                    "application/json"
719
+                ],
720
+                "produces": [
721
+                    "application/json"
722
+                ],
723
+                "summary": "地址簿集合规则详情",
724
+                "parameters": [
725
+                    {
726
+                        "type": "integer",
727
+                        "description": "ID",
728
+                        "name": "id",
729
+                        "in": "path",
730
+                        "required": true
731
+                    }
732
+                ],
733
+                "responses": {
734
+                    "200": {
735
+                        "description": "OK",
736
+                        "schema": {
737
+                            "allOf": [
738
+                                {
739
+                                    "$ref": "#/definitions/response.Response"
740
+                                },
741
+                                {
742
+                                    "type": "object",
743
+                                    "properties": {
744
+                                        "data": {
745
+                                            "$ref": "#/definitions/model.AddressBookCollectionRule"
746
+                                        }
747
+                                    }
748
+                                }
749
+                            ]
750
+                        }
751
+                    },
752
+                    "500": {
753
+                        "description": "Internal Server Error",
754
+                        "schema": {
755
+                            "$ref": "#/definitions/response.Response"
756
+                        }
757
+                    }
758
+                }
759
+            }
760
+        },
761
+        "/admin/address_book_collection_rule/list": {
762
+            "get": {
763
+                "security": [
764
+                    {
765
+                        "token": []
766
+                    }
767
+                ],
768
+                "description": "地址簿集合规则列表",
769
+                "consumes": [
770
+                    "application/json"
771
+                ],
772
+                "produces": [
773
+                    "application/json"
774
+                ],
775
+                "summary": "地址簿集合规则列表",
776
+                "parameters": [
777
+                    {
778
+                        "type": "integer",
779
+                        "description": "页码",
780
+                        "name": "page",
781
+                        "in": "query"
782
+                    },
783
+                    {
784
+                        "type": "integer",
785
+                        "description": "页大小",
786
+                        "name": "page_size",
787
+                        "in": "query"
788
+                    },
789
+                    {
790
+                        "type": "integer",
791
+                        "description": "是否是我的",
792
+                        "name": "is_my",
793
+                        "in": "query"
794
+                    },
795
+                    {
796
+                        "type": "integer",
797
+                        "description": "用户id",
798
+                        "name": "user_id",
799
+                        "in": "query"
800
+                    },
801
+                    {
802
+                        "type": "integer",
803
+                        "description": "地址簿集合id",
804
+                        "name": "collection_id",
805
+                        "in": "query"
806
+                    }
807
+                ],
808
+                "responses": {
809
+                    "200": {
810
+                        "description": "OK",
811
+                        "schema": {
812
+                            "allOf": [
813
+                                {
814
+                                    "$ref": "#/definitions/response.Response"
815
+                                },
816
+                                {
817
+                                    "type": "object",
818
+                                    "properties": {
819
+                                        "data": {
820
+                                            "$ref": "#/definitions/model.AddressBookCollectionList"
821
+                                        }
822
+                                    }
823
+                                }
824
+                            ]
825
+                        }
826
+                    },
827
+                    "500": {
828
+                        "description": "Internal Server Error",
829
+                        "schema": {
830
+                            "$ref": "#/definitions/response.Response"
831
+                        }
832
+                    }
833
+                }
834
+            }
835
+        },
836
+        "/admin/address_book_collection_rule/update": {
837
+            "post": {
838
+                "security": [
839
+                    {
840
+                        "token": []
841
+                    }
842
+                ],
843
+                "description": "地址簿集合规则编辑",
844
+                "consumes": [
845
+                    "application/json"
846
+                ],
847
+                "produces": [
848
+                    "application/json"
849
+                ],
850
+                "summary": "地址簿集合规则编辑",
851
+                "parameters": [
852
+                    {
853
+                        "description": "地址簿集合规则信息",
854
+                        "name": "body",
855
+                        "in": "body",
856
+                        "required": true,
857
+                        "schema": {
858
+                            "$ref": "#/definitions/model.AddressBookCollectionRule"
859
+                        }
860
+                    }
861
+                ],
862
+                "responses": {
863
+                    "200": {
864
+                        "description": "OK",
865
+                        "schema": {
866
+                            "allOf": [
867
+                                {
868
+                                    "$ref": "#/definitions/response.Response"
869
+                                },
870
+                                {
871
+                                    "type": "object",
872
+                                    "properties": {
873
+                                        "data": {
874
+                                            "$ref": "#/definitions/model.AddressBookCollection"
875
+                                        }
876
+                                    }
877
+                                }
878
+                            ]
879
+                        }
880
+                    },
881
+                    "500": {
882
+                        "description": "Internal Server Error",
883
+                        "schema": {
884
+                            "$ref": "#/definitions/response.Response"
885
+                        }
886
+                    }
887
+                }
888
+            }
889
+        },
342 890
         "/admin/app-config": {
343 891
             "get": {
344 892
                 "security": [
@@ -2473,6 +3021,9 @@
2473 3021
                 "alias": {
2474 3022
                     "type": "string"
2475 3023
                 },
3024
+                "collection_id": {
3025
+                    "type": "integer"
3026
+                },
2476 3027
                 "forceAlwaysRelay": {
2477 3028
                     "type": "boolean"
2478 3029
                 },
@@ -2694,6 +3245,9 @@
2694 3245
                 "name"
2695 3246
             ],
2696 3247
             "properties": {
3248
+                "collection_id": {
3249
+                    "type": "integer"
3250
+                },
2697 3251
                 "color": {
2698 3252
                     "type": "integer"
2699 3253
                 },
@@ -2781,6 +3335,12 @@
2781 3335
                 "alias": {
2782 3336
                     "type": "string"
2783 3337
                 },
3338
+                "collection": {
3339
+                    "$ref": "#/definitions/model.AddressBookCollection"
3340
+                },
3341
+                "collection_id": {
3342
+                    "type": "integer"
3343
+                },
2784 3344
                 "created_at": {
2785 3345
                     "type": "string"
2786 3346
                 },
@@ -2837,6 +3397,90 @@
2837 3397
                 }
2838 3398
             }
2839 3399
         },
3400
+        "model.AddressBookCollection": {
3401
+            "type": "object",
3402
+            "required": [
3403
+                "name"
3404
+            ],
3405
+            "properties": {
3406
+                "created_at": {
3407
+                    "type": "string"
3408
+                },
3409
+                "id": {
3410
+                    "type": "integer"
3411
+                },
3412
+                "name": {
3413
+                    "type": "string"
3414
+                },
3415
+                "updated_at": {
3416
+                    "type": "string"
3417
+                },
3418
+                "user_id": {
3419
+                    "type": "integer"
3420
+                }
3421
+            }
3422
+        },
3423
+        "model.AddressBookCollectionList": {
3424
+            "type": "object",
3425
+            "properties": {
3426
+                "list": {
3427
+                    "type": "array",
3428
+                    "items": {
3429
+                        "$ref": "#/definitions/model.AddressBookCollection"
3430
+                    }
3431
+                },
3432
+                "page": {
3433
+                    "type": "integer"
3434
+                },
3435
+                "page_size": {
3436
+                    "type": "integer"
3437
+                },
3438
+                "total": {
3439
+                    "type": "integer"
3440
+                }
3441
+            }
3442
+        },
3443
+        "model.AddressBookCollectionRule": {
3444
+            "type": "object",
3445
+            "required": [
3446
+                "collection_id",
3447
+                "rule",
3448
+                "to_id",
3449
+                "type"
3450
+            ],
3451
+            "properties": {
3452
+                "collection_id": {
3453
+                    "type": "integer"
3454
+                },
3455
+                "created_at": {
3456
+                    "type": "string"
3457
+                },
3458
+                "id": {
3459
+                    "type": "integer"
3460
+                },
3461
+                "rule": {
3462
+                    "description": "0: 无 1: 读 2: 读写  3: 完全控制",
3463
+                    "type": "integer",
3464
+                    "maximum": 3,
3465
+                    "minimum": 1
3466
+                },
3467
+                "to_id": {
3468
+                    "type": "integer"
3469
+                },
3470
+                "type": {
3471
+                    "description": "1: 个人 2: 群组",
3472
+                    "type": "integer",
3473
+                    "maximum": 2,
3474
+                    "minimum": 1
3475
+                },
3476
+                "updated_at": {
3477
+                    "type": "string"
3478
+                },
3479
+                "user_id": {
3480
+                    "type": "integer"
3481
+                }
3482
+            }
3483
+        },
2840 3484
         "model.AddressBookList": {
2841 3485
             "type": "object",
2842 3486
             "properties": {
@@ -3214,6 +3858,12 @@
3214 3858
         "model.Tag": {
3215 3859
             "type": "object",
3216 3860
             "properties": {
3861
+                "collection": {
3862
+                    "$ref": "#/definitions/model.AddressBookCollection"
3863
+                },
3864
+                "collection_id": {
3865
+                    "type": "integer"
3866
+                },
3217 3867
                 "color": {
3218 3868
                     "description": "color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba",
3219 3869
                     "type": "integer"

+ 392 - 0
docs/admin/admin_swagger.yaml

@@ -16,6 +16,8 @@ definitions:
16 16
     properties:
17 17
       alias:
18 18
         type: string
19
+      collection_id:
20
+        type: integer
19 21
       forceAlwaysRelay:
20 22
         type: boolean
21 23
       hash:
@@ -164,6 +166,8 @@ definitions:
164 166
     type: object
165 167
   admin.TagForm:
166 168
     properties:
169
+      collection_id:
170
+        type: integer
167 171
       color:
168 172
         type: integer
169 173
       id:
@@ -225,6 +229,10 @@ definitions:
225 229
     properties:
226 230
       alias:
227 231
         type: string
232
+      collection:
233
+        $ref: '#/definitions/model.AddressBookCollection'
234
+      collection_id:
235
+        type: integer
228 236
       created_at:
229 237
         type: string
230 238
       forceAlwaysRelay:
@@ -262,6 +270,64 @@ definitions:
262 270
       username:
263 271
         type: string
264 272
     type: object
273
+  model.AddressBookCollection:
274
+    properties:
275
+      created_at:
276
+        type: string
277
+      id:
278
+        type: integer
279
+      name:
280
+        type: string
281
+      updated_at:
282
+        type: string
283
+      user_id:
284
+        type: integer
285
+    required:
286
+    - name
287
+    type: object
288
+  model.AddressBookCollectionList:
289
+    properties:
290
+      list:
291
+        items:
292
+          $ref: '#/definitions/model.AddressBookCollection'
293
+        type: array
294
+      page:
295
+        type: integer
296
+      page_size:
297
+        type: integer
298
+      total:
299
+        type: integer
300
+    type: object
301
+  model.AddressBookCollectionRule:
302
+    properties:
303
+      collection_id:
304
+        type: integer
305
+      created_at:
306
+        type: string
307
+      id:
308
+        type: integer
309
+      rule:
310
+        description: '0: 无 1: 读 2: 读写  3: 完全控制'
311
+        maximum: 3
312
+        minimum: 1
313
+        type: integer
314
+      to_id:
315
+        type: integer
316
+      type:
317
+        description: '1: 个人 2: 群组'
318
+        maximum: 2
319
+        minimum: 1
320
+        type: integer
321
+      updated_at:
322
+        type: string
323
+      user_id:
324
+        type: integer
325
+    required:
326
+    - collection_id
327
+    - rule
328
+    - to_id
329
+    - type
330
+    type: object
265 331
   model.AddressBookList:
266 332
     properties:
267 333
       list:
@@ -511,6 +577,10 @@ definitions:
511 577
     - COMMON_STATUS_DISABLED
512 578
   model.Tag:
513 579
     properties:
580
+      collection:
581
+        $ref: '#/definitions/model.AddressBookCollection'
582
+      collection_id:
583
+        type: integer
514 584
       color:
515 585
         description: color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色,
516 586
           可以转成rgba
@@ -784,6 +854,328 @@ paths:
784 854
       summary: 地址簿编辑
785 855
       tags:
786 856
       - 地址簿
857
+  /admin/address_book_collection/create:
858
+    post:
859
+      consumes:
860
+      - application/json
861
+      description: 创建地址簿集合
862
+      parameters:
863
+      - description: 地址簿集合信息
864
+        in: body
865
+        name: body
866
+        required: true
867
+        schema:
868
+          $ref: '#/definitions/model.AddressBookCollection'
869
+      produces:
870
+      - application/json
871
+      responses:
872
+        "200":
873
+          description: OK
874
+          schema:
875
+            allOf:
876
+            - $ref: '#/definitions/response.Response'
877
+            - properties:
878
+                data:
879
+                  $ref: '#/definitions/model.AddressBookCollection'
880
+              type: object
881
+        "500":
882
+          description: Internal Server Error
883
+          schema:
884
+            $ref: '#/definitions/response.Response'
885
+      security:
886
+      - token: []
887
+      summary: 创建地址簿集合
888
+  /admin/address_book_collection/delete:
889
+    post:
890
+      consumes:
891
+      - application/json
892
+      description: 地址簿集合删除
893
+      parameters:
894
+      - description: 地址簿集合信息
895
+        in: body
896
+        name: body
897
+        required: true
898
+        schema:
899
+          $ref: '#/definitions/model.AddressBookCollection'
900
+      produces:
901
+      - application/json
902
+      responses:
903
+        "200":
904
+          description: OK
905
+          schema:
906
+            $ref: '#/definitions/response.Response'
907
+        "500":
908
+          description: Internal Server Error
909
+          schema:
910
+            $ref: '#/definitions/response.Response'
911
+      security:
912
+      - token: []
913
+      summary: 地址簿集合删除
914
+  /admin/address_book_collection/detail/{id}:
915
+    get:
916
+      consumes:
917
+      - application/json
918
+      description: 地址簿集合详情
919
+      parameters:
920
+      - description: ID
921
+        in: path
922
+        name: id
923
+        required: true
924
+        type: integer
925
+      produces:
926
+      - application/json
927
+      responses:
928
+        "200":
929
+          description: OK
930
+          schema:
931
+            allOf:
932
+            - $ref: '#/definitions/response.Response'
933
+            - properties:
934
+                data:
935
+                  $ref: '#/definitions/model.AddressBookCollection'
936
+              type: object
937
+        "500":
938
+          description: Internal Server Error
939
+          schema:
940
+            $ref: '#/definitions/response.Response'
941
+      security:
942
+      - token: []
943
+      summary: 地址簿集合详情
944
+  /admin/address_book_collection/list:
945
+    get:
946
+      consumes:
947
+      - application/json
948
+      description: 地址簿集合列表
949
+      parameters:
950
+      - description: 页码
951
+        in: query
952
+        name: page
953
+        type: integer
954
+      - description: 页大小
955
+        in: query
956
+        name: page_size
957
+        type: integer
958
+      - description: 是否是我的
959
+        in: query
960
+        name: is_my
961
+        type: integer
962
+      - description: 用户id
963
+        in: query
964
+        name: user_id
965
+        type: integer
966
+      produces:
967
+      - application/json
968
+      responses:
969
+        "200":
970
+          description: OK
971
+          schema:
972
+            allOf:
973
+            - $ref: '#/definitions/response.Response'
974
+            - properties:
975
+                data:
976
+                  $ref: '#/definitions/model.AddressBookCollectionList'
977
+              type: object
978
+        "500":
979
+          description: Internal Server Error
980
+          schema:
981
+            $ref: '#/definitions/response.Response'
982
+      security:
983
+      - token: []
984
+      summary: 地址簿集合列表
985
+  /admin/address_book_collection/update:
986
+    post:
987
+      consumes:
988
+      - application/json
989
+      description: 地址簿集合编辑
990
+      parameters:
991
+      - description: 地址簿集合信息
992
+        in: body
993
+        name: body
994
+        required: true
995
+        schema:
996
+          $ref: '#/definitions/model.AddressBookCollection'
997
+      produces:
998
+      - application/json
999
+      responses:
1000
+        "200":
1001
+          description: OK
1002
+          schema:
1003
+            allOf:
1004
+            - $ref: '#/definitions/response.Response'
1005
+            - properties:
1006
+                data:
1007
+                  $ref: '#/definitions/model.AddressBookCollection'
1008
+              type: object
1009
+        "500":
1010
+          description: Internal Server Error
1011
+          schema:
1012
+            $ref: '#/definitions/response.Response'
1013
+      security:
1014
+      - token: []
1015
+      summary: 地址簿集合编辑
1016
+  /admin/address_book_collection_rule/create:
1017
+    post:
1018
+      consumes:
1019
+      - application/json
1020
+      description: 创建地址簿集合规则
1021
+      parameters:
1022
+      - description: 地址簿集合规则信息
1023
+        in: body
1024
+        name: body
1025
+        required: true
1026
+        schema:
1027
+          $ref: '#/definitions/model.AddressBookCollectionRule'
1028
+      produces:
1029
+      - application/json
1030
+      responses:
1031
+        "200":
1032
+          description: OK
1033
+          schema:
1034
+            allOf:
1035
+            - $ref: '#/definitions/response.Response'
1036
+            - properties:
1037
+                data:
1038
+                  $ref: '#/definitions/model.AddressBookCollection'
1039
+              type: object
1040
+        "500":
1041
+          description: Internal Server Error
1042
+          schema:
1043
+            $ref: '#/definitions/response.Response'
1044
+      security:
1045
+      - token: []
1046
+      summary: 创建地址簿集合规则
1047
+  /admin/address_book_collection_rule/delete:
1048
+    post:
1049
+      consumes:
1050
+      - application/json
1051
+      description: 地址簿集合规则删除
1052
+      parameters:
1053
+      - description: 地址簿集合规则信息
1054
+        in: body
1055
+        name: body
1056
+        required: true
1057
+        schema:
1058
+          $ref: '#/definitions/model.AddressBookCollectionRule'
1059
+      produces:
1060
+      - application/json
1061
+      responses:
1062
+        "200":
1063
+          description: OK
1064
+          schema:
1065
+            $ref: '#/definitions/response.Response'
1066
+        "500":
1067
+          description: Internal Server Error
1068
+          schema:
1069
+            $ref: '#/definitions/response.Response'
1070
+      security:
1071
+      - token: []
1072
+      summary: 地址簿集合规则删除
1073
+  /admin/address_book_collection_rule/detail/{id}:
1074
+    get:
1075
+      consumes:
1076
+      - application/json
1077
+      description: 地址簿集合规则详情
1078
+      parameters:
1079
+      - description: ID
1080
+        in: path
1081
+        name: id
1082
+        required: true
1083
+        type: integer
1084
+      produces:
1085
+      - application/json
1086
+      responses:
1087
+        "200":
1088
+          description: OK
1089
+          schema:
1090
+            allOf:
1091
+            - $ref: '#/definitions/response.Response'
1092
+            - properties:
1093
+                data:
1094
+                  $ref: '#/definitions/model.AddressBookCollectionRule'
1095
+              type: object
1096
+        "500":
1097
+          description: Internal Server Error
1098
+          schema:
1099
+            $ref: '#/definitions/response.Response'
1100
+      security:
1101
+      - token: []
1102
+      summary: 地址簿集合规则详情
1103
+  /admin/address_book_collection_rule/list:
1104
+    get:
1105
+      consumes:
1106
+      - application/json
1107
+      description: 地址簿集合规则列表
1108
+      parameters:
1109
+      - description: 页码
1110
+        in: query
1111
+        name: page
1112
+        type: integer
1113
+      - description: 页大小
1114
+        in: query
1115
+        name: page_size
1116
+        type: integer
1117
+      - description: 是否是我的
1118
+        in: query
1119
+        name: is_my
1120
+        type: integer
1121
+      - description: 用户id
1122
+        in: query
1123
+        name: user_id
1124
+        type: integer
1125
+      - description: 地址簿集合id
1126
+        in: query
1127
+        name: collection_id
1128
+        type: integer
1129
+      produces:
1130
+      - application/json
1131
+      responses:
1132
+        "200":
1133
+          description: OK
1134
+          schema:
1135
+            allOf:
1136
+            - $ref: '#/definitions/response.Response'
1137
+            - properties:
1138
+                data:
1139
+                  $ref: '#/definitions/model.AddressBookCollectionList'
1140
+              type: object
1141
+        "500":
1142
+          description: Internal Server Error
1143
+          schema:
1144
+            $ref: '#/definitions/response.Response'
1145
+      security:
1146
+      - token: []
1147
+      summary: 地址簿集合规则列表
1148
+  /admin/address_book_collection_rule/update:
1149
+    post:
1150
+      consumes:
1151
+      - application/json
1152
+      description: 地址簿集合规则编辑
1153
+      parameters:
1154
+      - description: 地址簿集合规则信息
1155
+        in: body
1156
+        name: body
1157
+        required: true
1158
+        schema:
1159
+          $ref: '#/definitions/model.AddressBookCollectionRule'
1160
+      produces:
1161
+      - application/json
1162
+      responses:
1163
+        "200":
1164
+          description: OK
1165
+          schema:
1166
+            allOf:
1167
+            - $ref: '#/definitions/response.Response'
1168
+            - properties:
1169
+                data:
1170
+                  $ref: '#/definitions/model.AddressBookCollection'
1171
+              type: object
1172
+        "500":
1173
+          description: Internal Server Error
1174
+          schema:
1175
+            $ref: '#/definitions/response.Response'
1176
+      security:
1177
+      - token: []
1178
+      summary: 地址簿集合规则编辑
787 1179
   /admin/app-config:
788 1180
     get:
789 1181
       consumes:

+ 29 - 0
docs/api/api_docs.go

@@ -1445,9 +1445,38 @@ const docTemplateapi = `{
1445 1445
                 }
1446 1446
             }
1447 1447
         },
1448
+        "model.AddressBookCollection": {
1449
+            "type": "object",
1450
+            "required": [
1451
+                "name"
1452
+            ],
1453
+            "properties": {
1454
+                "created_at": {
1455
+                    "type": "string"
1456
+                },
1457
+                "id": {
1458
+                    "type": "integer"
1459
+                },
1460
+                "name": {
1461
+                    "type": "string"
1462
+                },
1463
+                "updated_at": {
1464
+                    "type": "string"
1465
+                },
1466
+                "user_id": {
1467
+                    "type": "integer"
1468
+                }
1469
+            }
1470
+        },
1448 1471
         "model.Tag": {
1449 1472
             "type": "object",
1450 1473
             "properties": {
1474
+                "collection": {
1475
+                    "$ref": "#/definitions/model.AddressBookCollection"
1476
+                },
1477
+                "collection_id": {
1478
+                    "type": "integer"
1479
+                },
1451 1480
                 "color": {
1452 1481
                     "description": "color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba",
1453 1482
                     "type": "integer"

+ 29 - 0
docs/api/api_swagger.json

@@ -1438,9 +1438,38 @@
1438 1438
                 }
1439 1439
             }
1440 1440
         },
1441
+        "model.AddressBookCollection": {
1442
+            "type": "object",
1443
+            "required": [
1444
+                "name"
1445
+            ],
1446
+            "properties": {
1447
+                "created_at": {
1448
+                    "type": "string"
1449
+                },
1450
+                "id": {
1451
+                    "type": "integer"
1452
+                },
1453
+                "name": {
1454
+                    "type": "string"
1455
+                },
1456
+                "updated_at": {
1457
+                    "type": "string"
1458
+                },
1459
+                "user_id": {
1460
+                    "type": "integer"
1461
+                }
1462
+            }
1463
+        },
1441 1464
         "model.Tag": {
1442 1465
             "type": "object",
1443 1466
             "properties": {
1467
+                "collection": {
1468
+                    "$ref": "#/definitions/model.AddressBookCollection"
1469
+                },
1470
+                "collection_id": {
1471
+                    "type": "integer"
1472
+                },
1444 1473
                 "color": {
1445 1474
                     "description": "color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba",
1446 1475
                     "type": "integer"

+ 19 - 0
docs/api/api_swagger.yaml

@@ -124,8 +124,27 @@ definitions:
124 124
       status:
125 125
         type: integer
126 126
     type: object
127
+  model.AddressBookCollection:
128
+    properties:
129
+      created_at:
130
+        type: string
131
+      id:
132
+        type: integer
133
+      name:
134
+        type: string
135
+      updated_at:
136
+        type: string
137
+      user_id:
138
+        type: integer
139
+    required:
140
+    - name
141
+    type: object
127 142
   model.Tag:
128 143
     properties:
144
+      collection:
145
+        $ref: '#/definitions/model.AddressBookCollection'
146
+      collection_id:
147
+        type: integer
129 148
       color:
130 149
         description: color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色,
131 150
           可以转成rgba

+ 33 - 4
http/controller/admin/addressBook.go

@@ -70,9 +70,14 @@ func (ct *AddressBook) Create(c *gin.Context) {
70 70
 	if !service.AllService.UserService.IsAdmin(u) || t.UserId == 0 {
71 71
 		t.UserId = u.Id
72 72
 	}
73
-	ex := service.AllService.AddressBookService.InfoByUserIdAndId(t.UserId, t.Id)
73
+	if t.CollectionId > 0 && !service.AllService.AddressBookService.CheckCollectionOwner(t.UserId, t.CollectionId) {
74
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
75
+		return
76
+	}
77
+
78
+	ex := service.AllService.AddressBookService.InfoByUserIdAndIdAndCid(t.UserId, t.Id, t.CollectionId)
74 79
 	if ex.RowId > 0 {
75
-		response.Fail(c, 101, response.TranslateMsg(c, "ItemExist"))
80
+		response.Fail(c, 101, response.TranslateMsg(c, "ItemExists"))
76 81
 		return
77 82
 	}
78 83
 
@@ -81,7 +86,7 @@ func (ct *AddressBook) Create(c *gin.Context) {
81 86
 		response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
82 87
 		return
83 88
 	}
84
-	response.Success(c, u)
89
+	response.Success(c, nil)
85 90
 }
86 91
 
87 92
 // BatchCreate 批量创建地址簿
@@ -113,7 +118,7 @@ func (ct *AddressBook) BatchCreate(c *gin.Context) {
113 118
 			continue
114 119
 		}
115 120
 		for _, ft := range f.Tags {
116
-			exTag := service.AllService.TagService.InfoByUserIdAndName(fu, ft)
121
+			exTag := service.AllService.TagService.InfoByUserIdAndNameAndCollectionId(fu, ft, 0)
117 122
 			if exTag.Id == 0 {
118 123
 				service.AllService.TagService.Create(&model.Tag{
119 124
 					UserId: fu,
@@ -161,6 +166,9 @@ func (ct *AddressBook) List(c *gin.Context) {
161 166
 		query.UserId = int(u.Id)
162 167
 	}
163 168
 	res := service.AllService.AddressBookService.List(query.Page, query.PageSize, func(tx *gorm.DB) {
169
+		tx.Preload("Collection", func(txc *gorm.DB) *gorm.DB {
170
+			return txc.Select("id,name")
171
+		})
164 172
 		if query.Id != "" {
165 173
 			tx.Where("id like ?", "%"+query.Id+"%")
166 174
 		}
@@ -173,7 +181,20 @@ func (ct *AddressBook) List(c *gin.Context) {
173 181
 		if query.Hostname != "" {
174 182
 			tx.Where("hostname like ?", "%"+query.Hostname+"%")
175 183
 		}
184
+		if query.CollectionId != nil && *query.CollectionId >= 0 {
185
+			tx.Where("collection_id = ?", query.CollectionId)
186
+		}
176 187
 	})
188
+
189
+	abCIds := make([]uint, 0)
190
+	for _, ab := range res.AddressBooks {
191
+		abCIds = append(abCIds, ab.CollectionId)
192
+	}
193
+	//获取地址簿名称
194
+	//cRes := service.AllService.AddressBookService.ListCollection(1, 999, func(tx *gorm.DB) {
195
+	//		tx.Where("id in ?", abCIds)
196
+	//})
197
+	//
177 198
 	response.Success(c, res)
178 199
 }
179 200
 
@@ -209,6 +230,10 @@ func (ct *AddressBook) Update(c *gin.Context) {
209 230
 		response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
210 231
 		return
211 232
 	}
233
+	if t.CollectionId > 0 && !service.AllService.AddressBookService.CheckCollectionOwner(t.UserId, t.CollectionId) {
234
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
235
+		return
236
+	}
212 237
 	err := service.AllService.AddressBookService.Update(t)
213 238
 	if err != nil {
214 239
 		response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
@@ -241,6 +266,10 @@ func (ct *AddressBook) Delete(c *gin.Context) {
241 266
 		return
242 267
 	}
243 268
 	t := service.AllService.AddressBookService.InfoByRowId(f.RowId)
269
+	if t.RowId == 0 {
270
+		response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
271
+		return
272
+	}
244 273
 	u := service.AllService.UserService.CurUser(c)
245 274
 	if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
246 275
 		response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))

+ 192 - 0
http/controller/admin/addressBookCollection.go

@@ -0,0 +1,192 @@
1
+package admin
2
+
3
+import (
4
+	"Gwen/global"
5
+	"Gwen/http/request/admin"
6
+	"Gwen/http/response"
7
+	"Gwen/model"
8
+	"Gwen/service"
9
+	"github.com/gin-gonic/gin"
10
+	"gorm.io/gorm"
11
+	"strconv"
12
+)
13
+
14
+type AddressBookCollection struct {
15
+}
16
+
17
+// Detail 地址簿集合
18
+// @AddressBookCollections 地址簿集合
19
+// @Summary 地址簿集合详情
20
+// @Description 地址簿集合详情
21
+// @Accept  json
22
+// @Produce  json
23
+// @Param id path int true "ID"
24
+// @Success 200 {object} response.Response{data=model.AddressBookCollection}
25
+// @Failure 500 {object} response.Response
26
+// @Router /admin/address_book_collection/detail/{id} [get]
27
+// @Security token
28
+func (abc *AddressBookCollection) Detail(c *gin.Context) {
29
+	id := c.Param("id")
30
+	iid, _ := strconv.Atoi(id)
31
+	t := service.AllService.AddressBookService.CollectionInfoById(uint(iid))
32
+	u := service.AllService.UserService.CurUser(c)
33
+	if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
34
+		response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
35
+		return
36
+	}
37
+	if t.Id > 0 {
38
+		response.Success(c, t)
39
+		return
40
+	}
41
+	response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
42
+	return
43
+}
44
+
45
+// Create 创建地址簿集合
46
+// @AddressBookCollections 地址簿集合
47
+// @Summary 创建地址簿集合
48
+// @Description 创建地址簿集合
49
+// @Accept  json
50
+// @Produce  json
51
+// @Param body body model.AddressBookCollection true "地址簿集合信息"
52
+// @Success 200 {object} response.Response{data=model.AddressBookCollection}
53
+// @Failure 500 {object} response.Response
54
+// @Router /admin/address_book_collection/create [post]
55
+// @Security token
56
+func (abc *AddressBookCollection) Create(c *gin.Context) {
57
+	f := &model.AddressBookCollection{}
58
+	if err := c.ShouldBindJSON(f); err != nil {
59
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
60
+		return
61
+	}
62
+	errList := global.Validator.ValidStruct(c, f)
63
+	if len(errList) > 0 {
64
+		response.Fail(c, 101, errList[0])
65
+		return
66
+	}
67
+	//t := f.ToAddressBookCollection()
68
+	t := f
69
+	u := service.AllService.UserService.CurUser(c)
70
+	if !service.AllService.UserService.IsAdmin(u) || t.UserId == 0 {
71
+		t.UserId = u.Id
72
+	}
73
+	err := service.AllService.AddressBookService.CreateCollection(t)
74
+	if err != nil {
75
+		response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
76
+		return
77
+	}
78
+	response.Success(c, nil)
79
+}
80
+
81
+// List 列表
82
+// @AddressBookCollections 地址簿集合
83
+// @Summary 地址簿集合列表
84
+// @Description 地址簿集合列表
85
+// @Accept  json
86
+// @Produce  json
87
+// @Param page query int false "页码"
88
+// @Param page_size query int false "页大小"
89
+// @Param is_my query int false "是否是我的"
90
+// @Param user_id query int false "用户id"
91
+// @Success 200 {object} response.Response{data=model.AddressBookCollectionList}
92
+// @Failure 500 {object} response.Response
93
+// @Router /admin/address_book_collection/list [get]
94
+// @Security token
95
+func (abc *AddressBookCollection) List(c *gin.Context) {
96
+	query := &admin.AddressBookCollectionQuery{}
97
+	if err := c.ShouldBindQuery(query); err != nil {
98
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
99
+		return
100
+	}
101
+	u := service.AllService.UserService.CurUser(c)
102
+	if !service.AllService.UserService.IsAdmin(u) || query.IsMy == 1 {
103
+		query.UserId = int(u.Id)
104
+	}
105
+	res := service.AllService.AddressBookService.ListCollection(query.Page, query.PageSize, func(tx *gorm.DB) {
106
+		if query.UserId > 0 {
107
+			tx.Where("user_id = ?", query.UserId)
108
+		}
109
+	})
110
+	response.Success(c, res)
111
+}
112
+
113
+// Update 编辑
114
+// @AddressBookCollections 地址簿集合
115
+// @Summary 地址簿集合编辑
116
+// @Description 地址簿集合编辑
117
+// @Accept  json
118
+// @Produce  json
119
+// @Param body body model.AddressBookCollection true "地址簿集合信息"
120
+// @Success 200 {object} response.Response{data=model.AddressBookCollection}
121
+// @Failure 500 {object} response.Response
122
+// @Router /admin/address_book_collection/update [post]
123
+// @Security token
124
+func (abc *AddressBookCollection) Update(c *gin.Context) {
125
+	f := &model.AddressBookCollection{}
126
+	if err := c.ShouldBindJSON(f); err != nil {
127
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
128
+		return
129
+	}
130
+	errList := global.Validator.ValidStruct(c, f)
131
+	if len(errList) > 0 {
132
+		response.Fail(c, 101, errList[0])
133
+		return
134
+	}
135
+	if f.Id == 0 {
136
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
137
+		return
138
+	}
139
+	t := f //f.ToAddressBookCollection()
140
+	u := service.AllService.UserService.CurUser(c)
141
+	if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
142
+		response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
143
+		return
144
+	}
145
+	err := service.AllService.AddressBookService.UpdateCollection(t)
146
+	if err != nil {
147
+		response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
148
+		return
149
+	}
150
+	response.Success(c, nil)
151
+}
152
+
153
+// Delete 删除
154
+// @AddressBookCollections 地址簿集合
155
+// @Summary 地址簿集合删除
156
+// @Description 地址簿集合删除
157
+// @Accept  json
158
+// @Produce  json
159
+// @Param body body model.AddressBookCollection true "地址簿集合信息"
160
+// @Success 200 {object} response.Response
161
+// @Failure 500 {object} response.Response
162
+// @Router /admin/address_book_collection/delete [post]
163
+// @Security token
164
+func (abc *AddressBookCollection) Delete(c *gin.Context) {
165
+	f := &model.AddressBookCollection{}
166
+	if err := c.ShouldBindJSON(f); err != nil {
167
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
168
+		return
169
+	}
170
+	id := f.Id
171
+	errList := global.Validator.ValidVar(c, id, "required,gt=0")
172
+	if len(errList) > 0 {
173
+		response.Fail(c, 101, errList[0])
174
+		return
175
+	}
176
+	t := service.AllService.AddressBookService.CollectionInfoById(f.Id)
177
+	u := service.AllService.UserService.CurUser(c)
178
+	if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
179
+		response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
180
+		return
181
+	}
182
+	if u.Id > 0 {
183
+		err := service.AllService.AddressBookService.DeleteCollection(t)
184
+		if err == nil {
185
+			response.Success(c, nil)
186
+			return
187
+		}
188
+		response.Fail(c, 101, err.Error())
189
+		return
190
+	}
191
+	response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
192
+}

+ 251 - 0
http/controller/admin/addressBookCollectionRule.go

@@ -0,0 +1,251 @@
1
+package admin
2
+
3
+import (
4
+	"Gwen/global"
5
+	"Gwen/http/request/admin"
6
+	"Gwen/http/response"
7
+	"Gwen/model"
8
+	"Gwen/service"
9
+	"github.com/gin-gonic/gin"
10
+	"gorm.io/gorm"
11
+	"strconv"
12
+)
13
+
14
+type AddressBookCollectionRule struct {
15
+}
16
+
17
+// List 列表
18
+// @AddressBookCollectionRule 地址簿集合规则
19
+// @Summary 地址簿集合规则列表
20
+// @Description 地址簿集合规则列表
21
+// @Accept  json
22
+// @Produce  json
23
+// @Param page query int false "页码"
24
+// @Param page_size query int false "页大小"
25
+// @Param is_my query int false "是否是我的"
26
+// @Param user_id query int false "用户id"
27
+// @Param collection_id query int false "地址簿集合id"
28
+// @Success 200 {object} response.Response{data=model.AddressBookCollectionList}
29
+// @Failure 500 {object} response.Response
30
+// @Router /admin/address_book_collection_rule/list [get]
31
+// @Security token
32
+func (abcr *AddressBookCollectionRule) List(c *gin.Context) {
33
+	query := &admin.AddressBookCollectionRuleQuery{}
34
+	if err := c.ShouldBindQuery(query); err != nil {
35
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
36
+		return
37
+	}
38
+	u := service.AllService.UserService.CurUser(c)
39
+	if !service.AllService.UserService.IsAdmin(u) || query.IsMy == 1 {
40
+		query.UserId = int(u.Id)
41
+	}
42
+
43
+	res := service.AllService.AddressBookService.ListRules(query.Page, query.PageSize, func(tx *gorm.DB) {
44
+		if query.UserId > 0 {
45
+			tx.Where("user_id = ?", query.UserId)
46
+		}
47
+		if query.CollectionId > 0 {
48
+			tx.Where("collection_id = ?", query.CollectionId)
49
+		}
50
+	})
51
+	response.Success(c, res)
52
+}
53
+
54
+// Detail 地址簿集合规则
55
+// @AddressBookCollectionRule 地址簿集合规则
56
+// @Summary 地址簿集合规则详情
57
+// @Description 地址簿集合规则详情
58
+// @Accept  json
59
+// @Produce  json
60
+// @Param id path int true "ID"
61
+// @Success 200 {object} response.Response{data=model.AddressBookCollectionRule}
62
+// @Failure 500 {object} response.Response
63
+// @Router /admin/address_book_collection_rule/detail/{id} [get]
64
+// @Security token
65
+func (abcr *AddressBookCollectionRule) Detail(c *gin.Context) {
66
+	id := c.Param("id")
67
+	iid, _ := strconv.Atoi(id)
68
+	t := service.AllService.AddressBookService.RuleInfoById(uint(iid))
69
+	u := service.AllService.UserService.CurUser(c)
70
+	if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
71
+		response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
72
+		return
73
+	}
74
+	if t.Id > 0 {
75
+		response.Success(c, t)
76
+		return
77
+	}
78
+	response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
79
+	return
80
+}
81
+
82
+// Create 创建地址簿集合规则
83
+// @AddressBookCollectionRule 地址簿集合规则
84
+// @Summary 创建地址簿集合规则
85
+// @Description 创建地址簿集合规则
86
+// @Accept  json
87
+// @Produce  json
88
+// @Param body body model.AddressBookCollectionRule true "地址簿集合规则信息"
89
+// @Success 200 {object} response.Response{data=model.AddressBookCollection}
90
+// @Failure 500 {object} response.Response
91
+// @Router /admin/address_book_collection_rule/create [post]
92
+// @Security token
93
+func (abcr *AddressBookCollectionRule) Create(c *gin.Context) {
94
+	f := &model.AddressBookCollectionRule{}
95
+	if err := c.ShouldBindJSON(f); err != nil {
96
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
97
+		return
98
+	}
99
+	errList := global.Validator.ValidStruct(c, f)
100
+	if len(errList) > 0 {
101
+		response.Fail(c, 101, errList[0])
102
+		return
103
+	}
104
+	if f.Type != model.ShareAddressBookRuleTypePersonal && f.Type != model.ShareAddressBookRuleTypeGroup {
105
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
106
+		return
107
+	}
108
+	//t := f.ToAddressBookCollection()
109
+	t := f
110
+	u := service.AllService.UserService.CurUser(c)
111
+	if t.UserId == 0 {
112
+		t.UserId = u.Id
113
+	}
114
+	msg, res := abcr.CheckForm(u, t)
115
+	if !res {
116
+		response.Fail(c, 101, response.TranslateMsg(c, msg))
117
+		return
118
+	}
119
+	err := service.AllService.AddressBookService.CreateRule(t)
120
+	if err != nil {
121
+		response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
122
+		return
123
+	}
124
+	response.Success(c, nil)
125
+}
126
+
127
+func (abcr *AddressBookCollectionRule) CheckForm(u *model.User, t *model.AddressBookCollectionRule) (string, bool) {
128
+	if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
129
+		return "NoAccess", false
130
+	}
131
+	if t.CollectionId > 0 && !service.AllService.AddressBookService.CheckCollectionOwner(t.UserId, t.CollectionId) {
132
+		return "ParamsError", false
133
+	}
134
+
135
+	//check to_id
136
+	if t.Type == model.ShareAddressBookRuleTypePersonal {
137
+		if t.ToId == t.UserId {
138
+			return "ParamsError", false
139
+		}
140
+		tou := service.AllService.UserService.InfoById(t.ToId)
141
+		if tou.Id == 0 {
142
+			return "ItemNotFound", false
143
+		}
144
+		//非管理员不能分享给非本组织用户
145
+		if tou.GroupId != u.GroupId && !service.AllService.UserService.IsAdmin(u) {
146
+			return "NoAccess", false
147
+		}
148
+	} else if t.Type == model.ShareAddressBookRuleTypeGroup {
149
+		if t.ToId != u.GroupId && !service.AllService.UserService.IsAdmin(u) {
150
+			return "NoAccess", false
151
+		}
152
+
153
+		tog := service.AllService.GroupService.InfoById(t.ToId)
154
+		if tog.Id == 0 {
155
+			return "ItemNotFound", false
156
+		}
157
+	} else {
158
+		return "ParamsError", false
159
+	}
160
+	// 重复检查
161
+	ex := service.AllService.AddressBookService.RulePersonalInfoByToIdAndCid(t.ToId, t.CollectionId)
162
+	if t.Id == 0 && ex.Id > 0 {
163
+		return "ItemExists", false
164
+	}
165
+	if t.Id > 0 && ex.Id > 0 && t.Id != ex.Id {
166
+		return "ItemExists", false
167
+	}
168
+	return "", true
169
+}
170
+
171
+// Update 编辑
172
+// @AddressBookCollectionRule 地址簿集合规则
173
+// @Summary 地址簿集合规则编辑
174
+// @Description 地址簿集合规则编辑
175
+// @Accept  json
176
+// @Produce  json
177
+// @Param body body model.AddressBookCollectionRule true "地址簿集合规则信息"
178
+// @Success 200 {object} response.Response{data=model.AddressBookCollection}
179
+// @Failure 500 {object} response.Response
180
+// @Router /admin/address_book_collection_rule/update [post]
181
+// @Security token
182
+func (abcr *AddressBookCollectionRule) Update(c *gin.Context) {
183
+	f := &model.AddressBookCollectionRule{}
184
+	if err := c.ShouldBindJSON(f); err != nil {
185
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
186
+		return
187
+	}
188
+	errList := global.Validator.ValidStruct(c, f)
189
+	if len(errList) > 0 {
190
+		response.Fail(c, 101, errList[0])
191
+		return
192
+	}
193
+	if f.Id == 0 {
194
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError"))
195
+		return
196
+	}
197
+	t := f //f.ToAddressBookCollection()
198
+	u := service.AllService.UserService.CurUser(c)
199
+	msg, res := abcr.CheckForm(u, t)
200
+	if !res {
201
+		response.Fail(c, 101, response.TranslateMsg(c, msg))
202
+		return
203
+	}
204
+	err := service.AllService.AddressBookService.UpdateRule(t)
205
+	if err != nil {
206
+		response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
207
+		return
208
+	}
209
+	response.Success(c, nil)
210
+}
211
+
212
+// Delete 删除
213
+// @AddressBookCollectionRule 地址簿集合规则
214
+// @Summary 地址簿集合规则删除
215
+// @Description 地址簿集合规则删除
216
+// @Accept  json
217
+// @Produce  json
218
+// @Param body body model.AddressBookCollectionRule true "地址簿集合规则信息"
219
+// @Success 200 {object} response.Response
220
+// @Failure 500 {object} response.Response
221
+// @Router /admin/address_book_collection_rule/delete [post]
222
+// @Security token
223
+func (abcr *AddressBookCollectionRule) Delete(c *gin.Context) {
224
+	f := &model.AddressBookCollectionRule{}
225
+	if err := c.ShouldBindJSON(f); err != nil {
226
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
227
+		return
228
+	}
229
+	id := f.Id
230
+	errList := global.Validator.ValidVar(c, id, "required,gt=0")
231
+	if len(errList) > 0 {
232
+		response.Fail(c, 101, errList[0])
233
+		return
234
+	}
235
+	t := service.AllService.AddressBookService.RuleInfoById(f.Id)
236
+	u := service.AllService.UserService.CurUser(c)
237
+	if !service.AllService.UserService.IsAdmin(u) && t.UserId != u.Id {
238
+		response.Fail(c, 101, response.TranslateMsg(c, "NoAccess"))
239
+		return
240
+	}
241
+	if t.Id > 0 {
242
+		err := service.AllService.AddressBookService.DeleteRule(t)
243
+		if err == nil {
244
+			response.Success(c, nil)
245
+			return
246
+		}
247
+		response.Fail(c, 101, err.Error())
248
+		return
249
+	}
250
+	response.Fail(c, 101, response.TranslateMsg(c, "ItemNotFound"))
251
+}

+ 2 - 0
http/controller/admin/audit.go

@@ -40,6 +40,7 @@ func (a *Audit) ConnList(c *gin.Context) {
40 40
 		if query.FromPeer != "" {
41 41
 			tx.Where("from_peer like ?", "%"+query.FromPeer+"%")
42 42
 		}
43
+		tx.Order("id desc")
43 44
 	})
44 45
 	response.Success(c, res)
45 46
 }
@@ -107,6 +108,7 @@ func (a *Audit) FileList(c *gin.Context) {
107 108
 		if query.FromPeer != "" {
108 109
 			tx.Where("from_peer like ?", "%"+query.FromPeer+"%")
109 110
 		}
111
+		tx.Order("id desc")
110 112
 	})
111 113
 	response.Success(c, res)
112 114
 }

+ 1 - 1
http/controller/admin/group.go

@@ -63,7 +63,7 @@ func (ct *Group) Create(c *gin.Context) {
63 63
 		response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
64 64
 		return
65 65
 	}
66
-	response.Success(c, u)
66
+	response.Success(c, nil)
67 67
 }
68 68
 
69 69
 // List 列表

+ 1 - 0
http/controller/admin/loginLog.go

@@ -64,6 +64,7 @@ func (ct *LoginLog) List(c *gin.Context) {
64 64
 		if query.UserId > 0 {
65 65
 			tx.Where("user_id = ?", query.UserId)
66 66
 		}
67
+		tx.Order("id desc")
67 68
 	})
68 69
 	response.Success(c, res)
69 70
 }

+ 1 - 1
http/controller/admin/oauth.go

@@ -202,7 +202,7 @@ func (o *Oauth) Create(c *gin.Context) {
202 202
 		response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
203 203
 		return
204 204
 	}
205
-	response.Success(c, u)
205
+	response.Success(c, nil)
206 206
 }
207 207
 
208 208
 // List 列表

+ 3 - 3
http/controller/admin/peer.go

@@ -59,13 +59,13 @@ func (ct *Peer) Create(c *gin.Context) {
59 59
 		response.Fail(c, 101, errList[0])
60 60
 		return
61 61
 	}
62
-	u := f.ToPeer()
63
-	err := service.AllService.PeerService.Create(u)
62
+	p := f.ToPeer()
63
+	err := service.AllService.PeerService.Create(p)
64 64
 	if err != nil {
65 65
 		response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
66 66
 		return
67 67
 	}
68
-	response.Success(c, u)
68
+	response.Success(c, nil)
69 69
 }
70 70
 
71 71
 // List 列表

+ 7 - 1
http/controller/admin/tag.go

@@ -73,7 +73,7 @@ func (ct *Tag) Create(c *gin.Context) {
73 73
 		response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
74 74
 		return
75 75
 	}
76
-	response.Success(c, u)
76
+	response.Success(c, nil)
77 77
 }
78 78
 
79 79
 // List 列表
@@ -101,9 +101,15 @@ func (ct *Tag) List(c *gin.Context) {
101 101
 		query.UserId = int(u.Id)
102 102
 	}
103 103
 	res := service.AllService.TagService.List(query.Page, query.PageSize, func(tx *gorm.DB) {
104
+		tx.Preload("Collection", func(txc *gorm.DB) *gorm.DB {
105
+			return txc.Select("id,name")
106
+		})
104 107
 		if query.UserId > 0 {
105 108
 			tx.Where("user_id = ?", query.UserId)
106 109
 		}
110
+		if query.CollectionId != nil && *query.CollectionId >= 0 {
111
+			tx.Where("collection_id = ?", query.CollectionId)
112
+		}
107 113
 	})
108 114
 	response.Success(c, res)
109 115
 }

+ 31 - 1
http/controller/admin/user.go

@@ -65,7 +65,7 @@ func (ct *User) Create(c *gin.Context) {
65 65
 		response.Fail(c, 101, response.TranslateMsg(c, "OperationFailed")+err.Error())
66 66
 		return
67 67
 	}
68
-	response.Success(c, u)
68
+	response.Success(c, nil)
69 69
 }
70 70
 
71 71
 // List 列表
@@ -293,3 +293,33 @@ func (ct *User) MyOauth(c *gin.Context) {
293 293
 	}
294 294
 	response.Success(c, res)
295 295
 }
296
+
297
+// groupUsers
298
+func (ct *User) GroupUsers(c *gin.Context) {
299
+	q := &admin.GroupUsersQuery{}
300
+	if err := c.ShouldBindJSON(q); err != nil {
301
+		response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
302
+		return
303
+	}
304
+	u := service.AllService.UserService.CurUser(c)
305
+	gid := u.GroupId
306
+	uid := u.Id
307
+	if service.AllService.UserService.IsAdmin(u) && q.UserId > 0 {
308
+		nu := service.AllService.UserService.InfoById(q.UserId)
309
+		gid = nu.GroupId
310
+		uid = q.UserId
311
+	}
312
+	res := service.AllService.UserService.List(1, 999, func(tx *gorm.DB) {
313
+		tx.Where("group_id = ?", gid)
314
+	})
315
+	var data []*adResp.GroupUsersPayload
316
+	for _, _u := range res.Users {
317
+		gup := &adResp.GroupUsersPayload{}
318
+		gup.FromUser(_u)
319
+		if _u.Id == uid {
320
+			gup.Status = 0
321
+		}
322
+		data = append(data, gup)
323
+	}
324
+	response.Success(c, data)
325
+}

+ 284 - 60
http/controller/api/ab.go

@@ -7,10 +7,13 @@ import (
7 7
 	"Gwen/http/response/api"
8 8
 	"Gwen/model"
9 9
 	"Gwen/service"
10
+	"Gwen/utils"
10 11
 	"encoding/json"
12
+	"errors"
11 13
 	"github.com/gin-gonic/gin"
12 14
 	"net/http"
13 15
 	"strconv"
16
+	"strings"
14 17
 )
15 18
 
16 19
 type Ab struct {
@@ -112,6 +115,35 @@ func (a *Ab) Tags(c *gin.Context) {
112 115
 	c.JSON(http.StatusOK, tags.Tags)
113 116
 }
114 117
 
118
+// PTags
119
+// @Tags 地址[Personal]
120
+// @Summary 标签
121
+// @Description 标签
122
+// @Accept  json
123
+// @Produce  json
124
+// @Param guid path string true "guid"
125
+// @Success 200 {object} model.TagList
126
+// @Failure 500 {object} response.ErrorResponse
127
+// @Router /ab/tags/{guid} [post]
128
+// @Security BearerAuth
129
+func (a *Ab) PTags(c *gin.Context) {
130
+	u := service.AllService.UserService.CurUser(c)
131
+	guid := c.Param("guid")
132
+	_, uid, cid, err := a.CheckGuid(u, guid)
133
+	if err != nil {
134
+		response.Error(c, response.TranslateMsg(c, err.Error()))
135
+		return
136
+	}
137
+
138
+	//check privileges
139
+	if !service.AllService.AddressBookService.CheckUserReadPrivilege(u, uid, cid) {
140
+		response.Error(c, response.TranslateMsg(c, "NoAccess"))
141
+		return
142
+	}
143
+	tags := service.AllService.TagService.ListByUserIdAndCollectionId(uid, cid)
144
+	c.JSON(http.StatusOK, tags.Tags)
145
+}
146
+
115 147
 // TagAdd
116 148
 // @Tags 地址[Personal]
117 149
 // @Summary 标签添加
@@ -124,19 +156,35 @@ func (a *Ab) Tags(c *gin.Context) {
124 156
 // @Router /ab/tag/add/{guid} [post]
125 157
 // @Security BearerAuth
126 158
 func (a *Ab) TagAdd(c *gin.Context) {
159
+
127 160
 	t := &model.Tag{}
128 161
 	err := c.ShouldBindJSON(t)
129 162
 	if err != nil {
130 163
 		response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
131 164
 		return
132 165
 	}
166
+
133 167
 	u := service.AllService.UserService.CurUser(c)
134
-	tag := service.AllService.TagService.InfoByUserIdAndName(u.Id, t.Name)
168
+	guid := c.Param("guid")
169
+	_, uid, cid, err := a.CheckGuid(u, guid)
170
+	if err != nil {
171
+		response.Error(c, response.TranslateMsg(c, err.Error()))
172
+		return
173
+	}
174
+
175
+	//check privileges
176
+	if !service.AllService.AddressBookService.CheckUserWritePrivilege(u, uid, cid) {
177
+		response.Error(c, response.TranslateMsg(c, "NoAccess"))
178
+		return
179
+	}
180
+
181
+	tag := service.AllService.TagService.InfoByUserIdAndNameAndCollectionId(uid, t.Name, cid)
135 182
 	if tag != nil && tag.Id != 0 {
136 183
 		response.Error(c, response.TranslateMsg(c, "ItemExists"))
137 184
 		return
138 185
 	}
139
-	t.UserId = u.Id
186
+	t.UserId = uid
187
+	t.CollectionId = cid
140 188
 	err = service.AllService.TagService.Create(t)
141 189
 	if err != nil {
142 190
 		response.Error(c, response.TranslateMsg(c, "OperationFailed")+err.Error())
@@ -157,6 +205,7 @@ func (a *Ab) TagAdd(c *gin.Context) {
157 205
 // @Router /ab/tag/rename/{guid} [put]
158 206
 // @Security BearerAuth
159 207
 func (a *Ab) TagRename(c *gin.Context) {
208
+
160 209
 	t := &requstform.TagRenameForm{}
161 210
 	err := c.ShouldBindJSON(t)
162 211
 	if err != nil {
@@ -164,12 +213,25 @@ func (a *Ab) TagRename(c *gin.Context) {
164 213
 		return
165 214
 	}
166 215
 	u := service.AllService.UserService.CurUser(c)
167
-	tag := service.AllService.TagService.InfoByUserIdAndName(u.Id, t.Old)
216
+	guid := c.Param("guid")
217
+	_, uid, cid, err := a.CheckGuid(u, guid)
218
+	if err != nil {
219
+		response.Error(c, response.TranslateMsg(c, err.Error()))
220
+		return
221
+	}
222
+
223
+	//check privileges
224
+	if !service.AllService.AddressBookService.CheckUserWritePrivilege(u, uid, cid) {
225
+		response.Error(c, response.TranslateMsg(c, "NoAccess"))
226
+		return
227
+	}
228
+
229
+	tag := service.AllService.TagService.InfoByUserIdAndNameAndCollectionId(uid, t.Old, cid)
168 230
 	if tag == nil || tag.Id == 0 {
169 231
 		response.Error(c, response.TranslateMsg(c, "ItemNotFound"))
170 232
 		return
171 233
 	}
172
-	ntag := service.AllService.TagService.InfoByUserIdAndName(u.Id, t.New)
234
+	ntag := service.AllService.TagService.InfoByUserIdAndNameAndCollectionId(uid, t.New, cid)
173 235
 	if ntag != nil && ntag.Id != 0 {
174 236
 		response.Error(c, response.TranslateMsg(c, "ItemExists"))
175 237
 		return
@@ -202,7 +264,20 @@ func (a *Ab) TagUpdate(c *gin.Context) {
202 264
 		return
203 265
 	}
204 266
 	u := service.AllService.UserService.CurUser(c)
205
-	tag := service.AllService.TagService.InfoByUserIdAndName(u.Id, t.Name)
267
+	guid := c.Param("guid")
268
+	_, uid, cid, err := a.CheckGuid(u, guid)
269
+	if err != nil {
270
+		response.Error(c, response.TranslateMsg(c, err.Error()))
271
+		return
272
+	}
273
+
274
+	//check privileges
275
+	if !service.AllService.AddressBookService.CheckUserWritePrivilege(u, uid, cid) {
276
+		response.Error(c, response.TranslateMsg(c, "NoAccess"))
277
+		return
278
+	}
279
+
280
+	tag := service.AllService.TagService.InfoByUserIdAndNameAndCollectionId(uid, t.Name, cid)
206 281
 	if tag == nil || tag.Id == 0 {
207 282
 		response.Error(c, response.TranslateMsg(c, "ItemNotFound"))
208 283
 		return
@@ -228,6 +303,7 @@ func (a *Ab) TagUpdate(c *gin.Context) {
228 303
 // @Router /ab/tag/{guid} [delete]
229 304
 // @Security BearerAuth
230 305
 func (a *Ab) TagDel(c *gin.Context) {
306
+
231 307
 	t := &[]string{}
232 308
 	err := c.ShouldBind(t)
233 309
 	if err != nil {
@@ -236,8 +312,21 @@ func (a *Ab) TagDel(c *gin.Context) {
236 312
 	}
237 313
 	//fmt.Println(t)
238 314
 	u := service.AllService.UserService.CurUser(c)
315
+	guid := c.Param("guid")
316
+	_, uid, cid, err := a.CheckGuid(u, guid)
317
+	if err != nil {
318
+		response.Error(c, response.TranslateMsg(c, err.Error()))
319
+		return
320
+	}
321
+
322
+	//check privileges
323
+	if !service.AllService.AddressBookService.CheckUserFullControlPrivilege(u, uid, cid) {
324
+		response.Error(c, response.TranslateMsg(c, "NoAccess"))
325
+		return
326
+	}
327
+
239 328
 	for _, name := range *t {
240
-		tag := service.AllService.TagService.InfoByUserIdAndName(u.Id, name)
329
+		tag := service.AllService.TagService.InfoByUserIdAndNameAndCollectionId(uid, name, cid)
241 330
 		if tag == nil || tag.Id == 0 {
242 331
 			response.Error(c, response.TranslateMsg(c, "ItemNotFound"))
243 332
 			return
@@ -272,7 +361,7 @@ func (a *Ab) Personal(c *gin.Context) {
272 361
 	       rule = json['rule'] ?? 0;
273 362
 	*/
274 363
 	if global.Config.Rustdesk.Personal == 1 {
275
-		guid := strconv.Itoa(int(user.GroupId)) + "-" + strconv.Itoa(int(user.Id))
364
+		guid := a.ComposeGuid(user.GroupId, user.Id, 0)
276 365
 		//如果返回了guid,后面的请求会有变化
277 366
 		c.JSON(http.StatusOK, gin.H{
278 367
 			"guid": guid,
@@ -315,38 +404,139 @@ func (a *Ab) Settings(c *gin.Context) {
315 404
 // @Router /ab/shared/profiles [post]
316 405
 // @Security BearerAuth
317 406
 func (a *Ab) SharedProfiles(c *gin.Context) {
318
-	//AbProfile.fromJson(Map<String, dynamic> json)
319
-	//: guid = json['guid'] ?? '',
320
-	//	name = json['name'] ?? '',
321
-	//	owner = json['owner'] ?? '',
322
-	//	note = json['note'] ?? '',
323
-	//	rule = json['rule'] ?? 0;
324
-	//暂时没必要返回数据,可能是为了共享地址簿
325
-	/*item := map[string]interface{}{
326
-		"guid":  "1",
327
-		"name":  "admin",
328
-		"owner": "admin",
329
-		"note":  "admin11",
330
-		"rule":  3,
331
-	}
332
-	item2 := map[string]interface{}{
333
-		"guid":  "2",
334
-		"name":  "admin2",
335
-		"owner": "admin2",
336
-		"note":  "admin22",
337
-		"rule":  2,
407
+
408
+	var res []*api.SharedProfilesPayload
409
+
410
+	user := service.AllService.UserService.CurUser(c)
411
+	myAbCollectionList := service.AllService.AddressBookService.ListCollectionByUserId(user.Id)
412
+	for _, ab := range myAbCollectionList.AddressBookCollection {
413
+		res = append(res, &api.SharedProfilesPayload{
414
+			Guid:  a.ComposeGuid(user.GroupId, user.Id, ab.Id),
415
+			Name:  ab.Name,
416
+			Owner: user.Username,
417
+			Rule:  model.ShareAddressBookRuleRuleFullControl,
418
+		})
419
+	}
420
+
421
+	allAbIds := make(map[uint]int) //用map去重,并保留最大Rule
422
+	allUserIds := make(map[uint]*model.User)
423
+	rules := service.AllService.AddressBookService.CollectionReadRules(user)
424
+	for _, rule := range rules {
425
+		//先判断是否存在
426
+		r, ok := allAbIds[rule.CollectionId]
427
+		if ok {
428
+			//再判断权限大小
429
+			if r < rule.Rule {
430
+				allAbIds[rule.CollectionId] = rule.Rule
431
+			}
432
+		} else {
433
+			allAbIds[rule.CollectionId] = rule.Rule
434
+			allUserIds[rule.UserId] = nil
435
+		}
436
+
437
+	}
438
+	abids := utils.Keys(allAbIds)
439
+	collections := service.AllService.AddressBookService.ListCollectionByIds(abids)
440
+
441
+	ids := utils.Keys(allUserIds)
442
+	allUsers := service.AllService.UserService.ListByIds(ids)
443
+	for _, u := range allUsers {
444
+		allUserIds[u.Id] = u
445
+	}
446
+
447
+	for _, collection := range collections {
448
+		_u, ok := allUserIds[collection.UserId]
449
+		if !ok {
450
+			continue
451
+		}
452
+		res = append(res, &api.SharedProfilesPayload{
453
+			Guid:  a.ComposeGuid(_u.GroupId, _u.Id, collection.Id),
454
+			Name:  collection.Name,
455
+			Owner: _u.Username,
456
+			Rule:  allAbIds[collection.Id],
457
+		})
338 458
 	}
339
-	c.JSON(http.StatusOK, gin.H{
340
-		"total": 2,
341
-		"data":  []interface{}{item, item2},
342
-	})*/
343 459
 
344 460
 	c.JSON(http.StatusOK, gin.H{
345
-		"total": 0,
346
-		"data":  nil,
461
+		"total": 0, //len(res),
462
+		"data":  res,
347 463
 	})
348 464
 }
349 465
 
466
+// ParseGuid
467
+func (a *Ab) ParseGuid(guid string) (gid, uid, cid uint) {
468
+	//用-切割 guid
469
+	guids := strings.Split(guid, "-")
470
+	if len(guids) < 2 {
471
+		return 0, 0, 0
472
+	}
473
+	if len(guids) != 3 {
474
+		cid = 0
475
+	} else {
476
+		s, err := strconv.Atoi(guids[2])
477
+		if err != nil {
478
+			return 0, 0, 0
479
+		}
480
+		cid = uint(s)
481
+	}
482
+	g, err := strconv.Atoi(guids[0])
483
+	if err != nil {
484
+		return 0, 0, 0
485
+	}
486
+	gid = uint(g)
487
+	u, err := strconv.Atoi(guids[1])
488
+	if err != nil {
489
+		return 0, 0, 0
490
+	}
491
+	uid = uint(u)
492
+	return
493
+}
494
+
495
+// ComposeGuid
496
+func (a *Ab) ComposeGuid(gid, uid, cid uint) string {
497
+	return strconv.Itoa(int(gid)) + "-" + strconv.Itoa(int(uid)) + "-" + strconv.Itoa(int(cid))
498
+}
499
+
500
+// CheckGuid
501
+func (a *Ab) CheckGuid(cu *model.User, guid string) (gid, uid, cid uint, err error) {
502
+	gid, uid, cid = a.ParseGuid(guid)
503
+	err = nil
504
+	if gid == 0 || uid == 0 {
505
+		err = errors.New("ParamsError")
506
+		return
507
+	}
508
+	u := &model.User{}
509
+	if cu.Id == uid {
510
+		u = cu
511
+	} else {
512
+		u = service.AllService.UserService.InfoById(uid)
513
+	}
514
+	if u == nil || u.Id == 0 {
515
+		err = errors.New("ParamsError")
516
+		return
517
+	}
518
+	if u.GroupId != gid {
519
+		err = errors.New("ParamsError")
520
+		return
521
+	}
522
+	if cid == 0 && cu.Id != uid {
523
+		err = errors.New("ParamsError")
524
+		return
525
+	}
526
+	if cid > 0 {
527
+		c := service.AllService.AddressBookService.CollectionInfoById(cid)
528
+		if c == nil || c.Id == 0 {
529
+			err = errors.New("ParamsError")
530
+			return
531
+		}
532
+		if c.UserId != uid {
533
+			err = errors.New("ParamsError")
534
+			return
535
+		}
536
+	}
537
+	return
538
+}
539
+
350 540
 // Peers
351 541
 // @Tags 地址[Personal]
352 542
 // @Summary 地址列表
@@ -361,8 +551,21 @@ func (a *Ab) SharedProfiles(c *gin.Context) {
361 551
 // @Router /ab/peers [post]
362 552
 // @Security BearerAuth
363 553
 func (a *Ab) Peers(c *gin.Context) {
364
-	user := service.AllService.UserService.CurUser(c)
365
-	al := service.AllService.AddressBookService.ListByUserId(user.Id, 1, 1000)
554
+	u := service.AllService.UserService.CurUser(c)
555
+	guid := c.Query("ab")
556
+	_, uid, cid, err := a.CheckGuid(u, guid)
557
+	if err != nil {
558
+		response.Error(c, response.TranslateMsg(c, err.Error()))
559
+		return
560
+	}
561
+
562
+	//check privileges
563
+	if !service.AllService.AddressBookService.CheckUserReadPrivilege(u, uid, cid) {
564
+		response.Error(c, response.TranslateMsg(c, "NoAccess"))
565
+		return
566
+	}
567
+
568
+	al := service.AllService.AddressBookService.ListByUserIdAndCollectionId(uid, cid, 1, 1000)
366 569
 	c.JSON(http.StatusOK, gin.H{
367 570
 		"total":            al.Total,
368 571
 		"data":             al.AddressBooks,
@@ -370,24 +573,6 @@ func (a *Ab) Peers(c *gin.Context) {
370 573
 	})
371 574
 }
372 575
 
373
-// PTags
374
-// @Tags 地址[Personal]
375
-// @Summary 标签
376
-// @Description 标签
377
-// @Accept  json
378
-// @Produce  json
379
-// @Param guid path string true "guid"
380
-// @Success 200 {object} model.TagList
381
-// @Failure 500 {object} response.ErrorResponse
382
-// @Router /ab/tags/{guid} [post]
383
-// @Security BearerAuth
384
-func (a *Ab) PTags(c *gin.Context) {
385
-	user := service.AllService.UserService.CurUser(c)
386
-
387
-	tags := service.AllService.TagService.ListByUserId(user.Id)
388
-	c.JSON(http.StatusOK, tags.Tags)
389
-}
390
-
391 576
 // PeerAdd
392 577
 // @Tags 地址[Personal]
393 578
 // @Summary 添加地址
@@ -402,18 +587,31 @@ func (a *Ab) PTags(c *gin.Context) {
402 587
 func (a *Ab) PeerAdd(c *gin.Context) {
403 588
 	// forceAlwaysRelay永远是字符串"false"
404 589
 	//f := &gin.H{}
405
-	//guid := c.Param("guid")
406 590
 	f := &requstform.PersonalAddressBookForm{}
407 591
 	err := c.ShouldBindJSON(f)
408 592
 	if err != nil {
409 593
 		response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
410 594
 		return
411 595
 	}
412
-	//fmt.Println(f)
596
+
413 597
 	u := service.AllService.UserService.CurUser(c)
414
-	f.UserId = u.Id
415
-	ab := f.ToAddressBook()
598
+	guid := c.Param("guid")
599
+	_, uid, cid, err := a.CheckGuid(u, guid)
600
+	if err != nil {
601
+		response.Error(c, response.TranslateMsg(c, err.Error()))
602
+		return
603
+	}
604
+
605
+	//check privileges
606
+	if !service.AllService.AddressBookService.CheckUserWritePrivilege(u, uid, cid) {
607
+		response.Error(c, response.TranslateMsg(c, "NoAccess"))
608
+		return
609
+	}
416 610
 
611
+	//fmt.Println(f)
612
+	f.UserId = uid
613
+	ab := f.ToAddressBook()
614
+	ab.CollectionId = cid
417 615
 	if ab.Platform == "" || ab.Username == "" || ab.Hostname == "" {
418 616
 		peer := service.AllService.PeerService.FindById(ab.Id)
419 617
 		if peer.RowId != 0 {
@@ -450,8 +648,21 @@ func (a *Ab) PeerDel(c *gin.Context) {
450 648
 		return
451 649
 	}
452 650
 	u := service.AllService.UserService.CurUser(c)
651
+	guid := c.Param("guid")
652
+	_, uid, cid, err := a.CheckGuid(u, guid)
653
+	if err != nil {
654
+		response.Error(c, response.TranslateMsg(c, err.Error()))
655
+		return
656
+	}
657
+
658
+	//check privileges
659
+	if !service.AllService.AddressBookService.CheckUserFullControlPrivilege(u, uid, cid) {
660
+		response.Error(c, response.TranslateMsg(c, "NoAccess"))
661
+		return
662
+	}
663
+
453 664
 	for _, id := range *f {
454
-		ab := service.AllService.AddressBookService.InfoByUserIdAndId(u.Id, id)
665
+		ab := service.AllService.AddressBookService.InfoByUserIdAndIdAndCid(uid, id, cid)
455 666
 		if ab == nil || ab.RowId == 0 {
456 667
 			response.Error(c, response.TranslateMsg(c, "ItemNotFound"))
457 668
 			return
@@ -485,10 +696,23 @@ func (a *Ab) PeerUpdate(c *gin.Context) {
485 696
 		response.Error(c, response.TranslateMsg(c, "ParamsError")+err.Error())
486 697
 		return
487 698
 	}
699
+	u := service.AllService.UserService.CurUser(c)
700
+	guid := c.Param("guid")
701
+	_, uid, cid, err := a.CheckGuid(u, guid)
702
+	if err != nil {
703
+		response.Error(c, response.TranslateMsg(c, err.Error()))
704
+		return
705
+	}
706
+
707
+	//check privileges
708
+	if !service.AllService.AddressBookService.CheckUserWritePrivilege(u, uid, cid) {
709
+		response.Error(c, response.TranslateMsg(c, "NoAccess"))
710
+		return
711
+	}
712
+
488 713
 	//fmt.Println(f)
489 714
 	//return
490
-	u := service.AllService.UserService.CurUser(c)
491
-	ab := service.AllService.AddressBookService.InfoByUserIdAndId(u.Id, f.Id)
715
+	ab := service.AllService.AddressBookService.InfoByUserIdAndIdAndCid(uid, f.Id, cid)
492 716
 	if ab == nil || ab.RowId == 0 {
493 717
 		response.Error(c, response.TranslateMsg(c, "ItemNotFound"))
494 718
 		return

+ 1 - 1
http/controller/api/index.go

@@ -50,7 +50,7 @@ func (i *Index) Heartbeat(c *gin.Context) {
50 50
 		return
51 51
 	}
52 52
 	peer := service.AllService.PeerService.FindByUuid(info.Uuid)
53
-	if peer == nil {
53
+	if peer == nil || peer.RowId == 0 {
54 54
 		c.JSON(http.StatusOK, gin.H{})
55 55
 		return
56 56
 	}

+ 25 - 5
http/request/admin/addressBook.go

@@ -23,6 +23,7 @@ type AddressBookForm struct {
23 23
 	Online           bool     `json:"online"`
24 24
 	LoginName        string   `json:"loginName" `
25 25
 	SameServer       bool     `json:"sameServer"`
26
+	CollectionId     uint     `json:"collection_id"`
26 27
 }
27 28
 
28 29
 func (a AddressBookForm) ToAddressBook() *model.AddressBook {
@@ -46,6 +47,7 @@ func (a AddressBookForm) ToAddressBook() *model.AddressBook {
46 47
 		Online:           a.Online,
47 48
 		LoginName:        a.LoginName,
48 49
 		SameServer:       a.SameServer,
50
+		CollectionId:     a.CollectionId,
49 51
 	}
50 52
 
51 53
 }
@@ -72,17 +74,19 @@ func (a AddressBookForm) ToAddressBooks() []*model.AddressBook {
72 74
 			Online:           a.Online,
73 75
 			LoginName:        a.LoginName,
74 76
 			SameServer:       a.SameServer,
77
+			CollectionId:     a.CollectionId,
75 78
 		})
76 79
 	}
77 80
 	return abs
78 81
 }
79 82
 
80 83
 type AddressBookQuery struct {
81
-	UserId   int    `form:"user_id"`
82
-	IsMy     int    `form:"is_my"`
83
-	Username string `form:"username"`
84
-	Hostname string `form:"hostname"`
85
-	Id       string `form:"id"`
84
+	UserId       int    `form:"user_id"`
85
+	CollectionId *int   `form:"collection_id"`
86
+	IsMy         int    `form:"is_my"`
87
+	Username     string `form:"username"`
88
+	Hostname     string `form:"hostname"`
89
+	Id           string `form:"id"`
86 90
 	PageQuery
87 91
 }
88 92
 
@@ -102,3 +106,19 @@ func (sbwcf ShareByWebClientForm) ToShareRecord() *model.ShareRecord {
102 106
 		Expire:       sbwcf.Expire,
103 107
 	}
104 108
 }
109
+
110
+type AddressBookCollectionQuery struct {
111
+	UserId int `form:"user_id"`
112
+	IsMy   int `form:"is_my"`
113
+	PageQuery
114
+}
115
+
116
+type AddressBookCollectionSimpleListQuery struct {
117
+	UserIds []uint `form:"user_ids"`
118
+}
119
+type AddressBookCollectionRuleQuery struct {
120
+	UserId       int `form:"user_id"`
121
+	CollectionId int `form:"collection_id"`
122
+	IsMy         int `form:"is_my"`
123
+	PageQuery
124
+}

+ 10 - 6
http/request/admin/tag.go

@@ -3,10 +3,11 @@ package admin
3 3
 import "Gwen/model"
4 4
 
5 5
 type TagForm struct {
6
-	Id     uint   `json:"id"`
7
-	Name   string `json:"name" validate:"required"`
8
-	Color  uint   `json:"color" validate:"required"`
9
-	UserId uint   `json:"user_id"`
6
+	Id           uint   `json:"id"`
7
+	Name         string `json:"name" validate:"required"`
8
+	Color        uint   `json:"color" validate:"required"`
9
+	UserId       uint   `json:"user_id"`
10
+	CollectionId uint   `json:"collection_id"`
10 11
 }
11 12
 
12 13
 func (f *TagForm) FromTag(group *model.Tag) *TagForm {
@@ -14,6 +15,7 @@ func (f *TagForm) FromTag(group *model.Tag) *TagForm {
14 15
 	f.Name = group.Name
15 16
 	f.Color = group.Color
16 17
 	f.UserId = group.UserId
18
+	f.CollectionId = group.CollectionId
17 19
 	return f
18 20
 }
19 21
 
@@ -23,11 +25,13 @@ func (f *TagForm) ToTag() *model.Tag {
23 25
 	i.Name = f.Name
24 26
 	i.Color = f.Color
25 27
 	i.UserId = f.UserId
28
+	i.CollectionId = f.CollectionId
26 29
 	return i
27 30
 }
28 31
 
29 32
 type TagQuery struct {
30
-	UserId int `form:"user_id"`
31
-	IsMy   int `form:"is_my"`
33
+	UserId       int  `form:"user_id"`
34
+	IsMy         int  `form:"is_my"`
35
+	CollectionId *int `form:"collection_id"`
32 36
 	PageQuery
33 37
 }

+ 4 - 0
http/request/admin/user.go

@@ -55,3 +55,7 @@ type ChangeCurPasswordForm struct {
55 55
 	OldPassword string `json:"old_password" validate:"required,gte=4,lte=20"`
56 56
 	NewPassword string `json:"new_password" validate:"required,gte=4,lte=20"`
57 57
 }
58
+type GroupUsersQuery struct {
59
+	IsMy   int  `json:"is_my"`
60
+	UserId uint `json:"user_id"`
61
+}

+ 15 - 1
http/response/admin/user.go

@@ -1,5 +1,7 @@
1 1
 package admin
2 2
 
3
+import "Gwen/model"
4
+
3 5
 type LoginPayload struct {
4 6
 	Username   string   `json:"username"`
5 7
 	Token      string   `json:"token"`
@@ -8,7 +10,7 @@ type LoginPayload struct {
8 10
 }
9 11
 
10 12
 var UserRouteNames = []string{
11
-	"MyTagList", "MyAddressBookList", "MyInfo",
13
+	"MyTagList", "MyAddressBookList", "MyInfo", "MyAddressBookCollection",
12 14
 }
13 15
 var AdminRouteNames = []string{"*"}
14 16
 
@@ -16,3 +18,15 @@ type UserOauthItem struct {
16 18
 	ThirdType string `json:"third_type"`
17 19
 	Status    int    `json:"status"`
18 20
 }
21
+
22
+type GroupUsersPayload struct {
23
+	Id       uint   `json:"id"`
24
+	Username string `json:"username"`
25
+	Status   int    `json:"status"`
26
+}
27
+
28
+func (g *GroupUsersPayload) FromUser(user *model.User) {
29
+	g.Id = user.Id
30
+	g.Username = user.Username
31
+	g.Status = 1
32
+}

+ 8 - 0
http/response/api/ab.go

@@ -7,3 +7,11 @@ type AbList struct {
7 7
 	Tags      []string             `json:"tags,omitempty"`
8 8
 	TagColors string               `json:"tag_colors,omitempty"`
9 9
 }
10
+
11
+type SharedProfilesPayload struct {
12
+	Guid  string `json:"guid"`
13
+	Name  string `json:"name"`
14
+	Owner string `json:"owner"`
15
+	Note  string `json:"note"`
16
+	Rule  int    `json:"rule"`
17
+}

+ 26 - 0
http/router/admin.go

@@ -28,6 +28,8 @@ func Init(g *gin.Engine) {
28 28
 	OauthBind(adg)
29 29
 	LoginLogBind(adg)
30 30
 	AuditBind(adg)
31
+	AddressBookCollectionBind(adg)
32
+	AddressBookCollectionRuleBind(adg)
31 33
 	rs := &admin.Rustdesk{}
32 34
 	adg.GET("/server-config", rs.ServerConfig)
33 35
 	adg.GET("/app-config", rs.AppConfig)
@@ -48,6 +50,7 @@ func UserBind(rg *gin.RouterGroup) {
48 50
 		aR.GET("/current", cont.Current)
49 51
 		aR.POST("/changeCurPwd", cont.ChangeCurPwd)
50 52
 		aR.POST("/myOauth", cont.MyOauth)
53
+		aR.POST("/groupUsers", cont.GroupUsers)
51 54
 	}
52 55
 	aRP := rg.Group("/user").Use(middleware.AdminPrivilege())
53 56
 	{
@@ -152,6 +155,29 @@ func AuditBind(rg *gin.RouterGroup) {
152 155
 	afR.GET("/list", cont.FileList)
153 156
 	afR.POST("/delete", cont.FileDelete)
154 157
 }
158
+func AddressBookCollectionBind(rg *gin.RouterGroup) {
159
+	aR := rg.Group("/address_book_collection")
160
+	{
161
+		cont := &admin.AddressBookCollection{}
162
+		aR.GET("/list", cont.List)
163
+		aR.GET("/detail/:id", cont.Detail)
164
+		aR.POST("/create", cont.Create)
165
+		aR.POST("/update", cont.Update)
166
+		aR.POST("/delete", cont.Delete)
167
+	}
168
+
169
+}
170
+func AddressBookCollectionRuleBind(rg *gin.RouterGroup) {
171
+	aR := rg.Group("/address_book_collection_rule")
172
+	{
173
+		cont := &admin.AddressBookCollectionRule{}
174
+		aR.GET("/list", cont.List)
175
+		aR.GET("/detail/:id", cont.Detail)
176
+		aR.POST("/create", cont.Create)
177
+		aR.POST("/update", cont.Update)
178
+		aR.POST("/delete", cont.Delete)
179
+	}
180
+}
155 181
 
156 182
 /*
157 183
 func FileBind(rg *gin.RouterGroup) {

+ 52 - 16
model/addressBook.go

@@ -19,22 +19,24 @@ import "Gwen/model/custom_types"
19 19
 
20 20
 // AddressBook 有些字段是Personal才会上传的
21 21
 type AddressBook struct {
22
-	RowId            uint                  `gorm:"primaryKey" json:"row_id"`
23
-	Id               string                `json:"id" gorm:"default:0;not null;index"`
24
-	Username         string                `json:"username" gorm:"default:'';not null;"`
25
-	Password         string                `json:"password" gorm:"default:'';not null;"`
26
-	Hostname         string                `json:"hostname" gorm:"default:'';not null;"`
27
-	Alias            string                `json:"alias" gorm:"default:'';not null;"`
28
-	Platform         string                `json:"platform" gorm:"default:'';not null;"`
29
-	Tags             custom_types.AutoJson `json:"tags" gorm:"not null;" swaggertype:"array,string"`
30
-	Hash             string                `json:"hash" gorm:"default:'';not null;"`
31
-	UserId           uint                  `json:"user_id" gorm:"default:0;not null;index"`
32
-	ForceAlwaysRelay bool                  `json:"forceAlwaysRelay" gorm:"default:0;not null;"`
33
-	RdpPort          string                `json:"rdpPort" gorm:"default:'';not null;"`
34
-	RdpUsername      string                `json:"rdpUsername" gorm:"default:'';not null;"`
35
-	Online           bool                  `json:"online" gorm:"default:0;not null;"`
36
-	LoginName        string                `json:"loginName" gorm:"default:'';not null;"`
37
-	SameServer       bool                  `json:"sameServer" gorm:"default:0;not null;"`
22
+	RowId            uint                   `gorm:"primaryKey" json:"row_id"`
23
+	Id               string                 `json:"id" gorm:"default:0;not null;index"`
24
+	Username         string                 `json:"username" gorm:"default:'';not null;"`
25
+	Password         string                 `json:"password" gorm:"default:'';not null;"`
26
+	Hostname         string                 `json:"hostname" gorm:"default:'';not null;"`
27
+	Alias            string                 `json:"alias" gorm:"default:'';not null;"`
28
+	Platform         string                 `json:"platform" gorm:"default:'';not null;"`
29
+	Tags             custom_types.AutoJson  `json:"tags" gorm:"not null;" swaggertype:"array,string"`
30
+	Hash             string                 `json:"hash" gorm:"default:'';not null;"`
31
+	UserId           uint                   `json:"user_id" gorm:"default:0;not null;index"`
32
+	ForceAlwaysRelay bool                   `json:"forceAlwaysRelay" gorm:"default:0;not null;"`
33
+	RdpPort          string                 `json:"rdpPort" gorm:"default:'';not null;"`
34
+	RdpUsername      string                 `json:"rdpUsername" gorm:"default:'';not null;"`
35
+	Online           bool                   `json:"online" gorm:"default:0;not null;"`
36
+	LoginName        string                 `json:"loginName" gorm:"default:'';not null;"`
37
+	SameServer       bool                   `json:"sameServer" gorm:"default:0;not null;"`
38
+	CollectionId     uint                   `json:"collection_id" gorm:"default:0;not null;index"`
39
+	Collection       *AddressBookCollection `json:"collection,omitempty"`
38 40
 	TimeModel
39 41
 }
40 42
 
@@ -42,3 +44,37 @@ type AddressBookList struct {
42 44
 	AddressBooks []*AddressBook `json:"list"`
43 45
 	Pagination
44 46
 }
47
+
48
+type AddressBookCollection struct {
49
+	IdModel
50
+	UserId uint   `json:"user_id" gorm:"default:0;not null;index"`
51
+	Name   string `json:"name" gorm:"default:'';not null;" validate:"required"`
52
+	TimeModel
53
+}
54
+type AddressBookCollectionList struct {
55
+	AddressBookCollection []*AddressBookCollection `json:"list"`
56
+	Pagination
57
+}
58
+type AddressBookCollectionRule struct {
59
+	IdModel
60
+	UserId       uint `json:"user_id" gorm:"default:0;not null;"`
61
+	CollectionId uint `json:"collection_id" gorm:"default:0;not null;index" validate:"required"`
62
+	Rule         int  `json:"rule" gorm:"default:0;not null;" validate:"required,gte=1,lte=3"` // 0: 无 1: 读 2: 读写  3: 完全控制
63
+	Type         int  `json:"type" gorm:"default:1;not null;" validate:"required,gte=1,lte=2"` // 1: 个人 2: 群组
64
+	ToId         uint `json:"to_id" gorm:"default:0;not null;" validate:"required,gt=0"`
65
+	TimeModel
66
+}
67
+type AddressBookCollectionRuleList struct {
68
+	AddressBookCollectionRule []*AddressBookCollectionRule `json:"list"`
69
+	Pagination
70
+}
71
+
72
+const (
73
+	ShareAddressBookRuleTypePersonal = 1
74
+	ShareAddressBookRuleTypeGroup    = 2
75
+)
76
+const (
77
+	ShareAddressBookRuleRuleRead        = 1
78
+	ShareAddressBookRuleRuleReadWrite   = 2
79
+	ShareAddressBookRuleRuleFullControl = 3
80
+)

+ 5 - 3
model/tag.go

@@ -2,9 +2,11 @@ package model
2 2
 
3 3
 type Tag struct {
4 4
 	IdModel
5
-	Name   string `json:"name" gorm:"default:'';not null;"`
6
-	UserId uint   `json:"user_id" gorm:"default:0;not null;index"`
7
-	Color  uint   `json:"color" gorm:"default:0;not null;"` //color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba
5
+	Name         string                 `json:"name" gorm:"default:'';not null;"`
6
+	UserId       uint                   `json:"user_id" gorm:"default:0;not null;index"`
7
+	Color        uint                   `json:"color" gorm:"default:0;not null;"` //color 是flutter的颜色值,从0x00000000 到 0xFFFFFFFF; 前两位表示透明度,后面6位表示颜色, 可以转成rgba
8
+	CollectionId uint                   `json:"collection_id" gorm:"default:0;not null;index"`
9
+	Collection   *AddressBookCollection `json:"collection,omitempty"`
8 10
 	TimeModel
9 11
 }
10 12
 

+ 163 - 8
service/addressBook.go

@@ -22,6 +22,12 @@ func (s *AddressBookService) InfoByUserIdAndId(userid uint, id string) *model.Ad
22 22
 	global.DB.Where("user_id = ? and id = ?", userid, id).First(p)
23 23
 	return p
24 24
 }
25
+
26
+func (s *AddressBookService) InfoByUserIdAndIdAndCid(userid uint, id string, cid uint) *model.AddressBook {
27
+	p := &model.AddressBook{}
28
+	global.DB.Where("user_id = ? and id = ? and collection_id = ?", userid, id, cid).First(p)
29
+	return p
30
+}
25 31
 func (s *AddressBookService) InfoByRowId(id uint) *model.AddressBook {
26 32
 	p := &model.AddressBook{}
27 33
 	global.DB.Where("row_id = ?", id).First(p)
@@ -96,7 +102,7 @@ func (s *AddressBookService) UpdateAddressBook(abs []*model.AddressBook, userId
96 102
 
97 103
 }
98 104
 
99
-func (t *AddressBookService) List(page, pageSize uint, where func(tx *gorm.DB)) (res *model.AddressBookList) {
105
+func (s *AddressBookService) List(page, pageSize uint, where func(tx *gorm.DB)) (res *model.AddressBookList) {
100 106
 	res = &model.AddressBookList{}
101 107
 	res.Page = int64(page)
102 108
 	res.PageSize = int64(pageSize)
@@ -111,34 +117,34 @@ func (t *AddressBookService) List(page, pageSize uint, where func(tx *gorm.DB))
111 117
 }
112 118
 
113 119
 // Create 创建
114
-func (t *AddressBookService) Create(u *model.AddressBook) error {
120
+func (s *AddressBookService) Create(u *model.AddressBook) error {
115 121
 	res := global.DB.Create(u).Error
116 122
 	return res
117 123
 }
118
-func (t *AddressBookService) Delete(u *model.AddressBook) error {
124
+func (s *AddressBookService) Delete(u *model.AddressBook) error {
119 125
 	return global.DB.Delete(u).Error
120 126
 }
121 127
 
122 128
 // Update 更新
123
-func (t *AddressBookService) Update(u *model.AddressBook) error {
124
-	return global.DB.Model(u).Updates(u).Error
129
+func (s *AddressBookService) Update(u *model.AddressBook) error {
130
+	return global.DB.Model(u).Select("*").Omit("created_at").Updates(u).Error
125 131
 }
126 132
 
127 133
 // ShareByWebClient 分享
128
-func (t *AddressBookService) ShareByWebClient(m *model.ShareRecord) error {
134
+func (s *AddressBookService) ShareByWebClient(m *model.ShareRecord) error {
129 135
 	m.ShareToken = uuid.New().String()
130 136
 	return global.DB.Create(m).Error
131 137
 }
132 138
 
133 139
 // SharedPeer
134
-func (t *AddressBookService) SharedPeer(shareToken string) *model.ShareRecord {
140
+func (s *AddressBookService) SharedPeer(shareToken string) *model.ShareRecord {
135 141
 	m := &model.ShareRecord{}
136 142
 	global.DB.Where("share_token = ?", shareToken).First(m)
137 143
 	return m
138 144
 }
139 145
 
140 146
 // PlatformFromOs
141
-func (t *AddressBookService) PlatformFromOs(os string) string {
147
+func (s *AddressBookService) PlatformFromOs(os string) string {
142 148
 	if strings.Contains(os, "Android") || strings.Contains(os, "android") {
143 149
 		return "Android"
144 150
 	}
@@ -153,3 +159,152 @@ func (t *AddressBookService) PlatformFromOs(os string) string {
153 159
 	}
154 160
 	return ""
155 161
 }
162
+func (s *AddressBookService) ListByUserIdAndCollectionId(userId, cid, page, pageSize uint) (res *model.AddressBookList) {
163
+	res = s.List(page, pageSize, func(tx *gorm.DB) {
164
+		tx.Where("user_id = ? and collection_id = ?", userId, cid)
165
+	})
166
+	return
167
+}
168
+func (s *AddressBookService) ListCollection(page, pageSize uint, where func(tx *gorm.DB)) (res *model.AddressBookCollectionList) {
169
+	res = &model.AddressBookCollectionList{}
170
+	res.Page = int64(page)
171
+	res.PageSize = int64(pageSize)
172
+	tx := global.DB.Model(&model.AddressBookCollection{})
173
+	if where != nil {
174
+		where(tx)
175
+	}
176
+	tx.Count(&res.Total)
177
+	tx.Scopes(Paginate(page, pageSize))
178
+	tx.Find(&res.AddressBookCollection)
179
+	return
180
+}
181
+func (s *AddressBookService) ListCollectionByIds(ids []uint) (res []*model.AddressBookCollection) {
182
+	global.DB.Where("id in ?", ids).Find(&res)
183
+	return res
184
+}
185
+
186
+func (s *AddressBookService) ListCollectionByUserId(userId uint) (res *model.AddressBookCollectionList) {
187
+	res = s.ListCollection(1, 100, func(tx *gorm.DB) {
188
+		tx.Where("user_id = ?", userId)
189
+	})
190
+	return
191
+}
192
+func (s *AddressBookService) CollectionInfoById(id uint) *model.AddressBookCollection {
193
+	p := &model.AddressBookCollection{}
194
+	global.DB.Where("id = ?", id).First(p)
195
+	return p
196
+}
197
+
198
+func (s *AddressBookService) CollectionReadRules(user *model.User) (res []*model.AddressBookCollectionRule) {
199
+	// personalRules
200
+	var personalRules []*model.AddressBookCollectionRule
201
+	tx2 := global.DB.Model(&model.AddressBookCollectionRule{})
202
+	tx2.Where("type = ? and to_id = ? and rule > 0", model.ShareAddressBookRuleTypePersonal, user.Id).Find(&personalRules)
203
+	res = append(res, personalRules...)
204
+
205
+	//group
206
+	var groupRules []*model.AddressBookCollectionRule
207
+	tx3 := global.DB.Model(&model.AddressBookCollectionRule{})
208
+	tx3.Where("type = ? and to_id = ? and rule > 0", model.ShareAddressBookRuleTypeGroup, user.GroupId).Find(&groupRules)
209
+	res = append(res, groupRules...)
210
+	return
211
+}
212
+
213
+func (s *AddressBookService) UserMaxRule(user *model.User, uid, cid uint) int {
214
+	// ismy?
215
+	if user.Id == uid {
216
+		return model.ShareAddressBookRuleRuleFullControl
217
+	}
218
+	max := 0
219
+	personalRules := &model.AddressBookCollectionRule{}
220
+	tx := global.DB.Model(personalRules)
221
+	tx.Where("type = ? and collection_id = ? and to_id = ?", model.ShareAddressBookRuleTypePersonal, cid, user.Id).First(&personalRules)
222
+	if personalRules.Id != 0 {
223
+		max = personalRules.Rule
224
+		if max == model.ShareAddressBookRuleRuleFullControl {
225
+			return max
226
+		}
227
+	}
228
+
229
+	groupRules := &model.AddressBookCollectionRule{}
230
+	tx2 := global.DB.Model(groupRules)
231
+	tx2.Where("type = ? and collection_id = ? and to_id = ?", model.ShareAddressBookRuleTypeGroup, cid, user.GroupId).First(&groupRules)
232
+	if groupRules.Id != 0 {
233
+		if groupRules.Rule > max {
234
+			max = groupRules.Rule
235
+		}
236
+		if max == model.ShareAddressBookRuleRuleFullControl {
237
+			return max
238
+		}
239
+	}
240
+	return max
241
+}
242
+
243
+func (s *AddressBookService) CheckUserReadPrivilege(user *model.User, uid, cid uint) bool {
244
+	return s.UserMaxRule(user, uid, cid) >= model.ShareAddressBookRuleRuleRead
245
+}
246
+func (s *AddressBookService) CheckUserWritePrivilege(user *model.User, uid, cid uint) bool {
247
+	return s.UserMaxRule(user, uid, cid) >= model.ShareAddressBookRuleRuleReadWrite
248
+}
249
+func (s *AddressBookService) CheckUserFullControlPrivilege(user *model.User, uid, cid uint) bool {
250
+	return s.UserMaxRule(user, uid, cid) >= model.ShareAddressBookRuleRuleFullControl
251
+}
252
+
253
+func (s *AddressBookService) CreateCollection(t *model.AddressBookCollection) error {
254
+	return global.DB.Create(t).Error
255
+}
256
+
257
+func (s *AddressBookService) UpdateCollection(t *model.AddressBookCollection) error {
258
+	return global.DB.Model(t).Updates(t).Error
259
+}
260
+
261
+func (s *AddressBookService) DeleteCollection(t *model.AddressBookCollection) error {
262
+	//删除集合下的所有规则、地址簿,再删除集合
263
+	tx := global.DB.Begin()
264
+	tx.Where("collection_id = ?", t.Id).Delete(&model.AddressBookCollectionRule{})
265
+	tx.Where("collection_id = ?", t.Id).Delete(&model.AddressBook{})
266
+	tx.Delete(t)
267
+	return tx.Commit().Error
268
+}
269
+
270
+func (s *AddressBookService) RuleInfoById(u uint) *model.AddressBookCollectionRule {
271
+	p := &model.AddressBookCollectionRule{}
272
+	global.DB.Where("id = ?", u).First(p)
273
+	return p
274
+}
275
+func (s *AddressBookService) RulePersonalInfoByToIdAndCid(toid, cid uint) *model.AddressBookCollectionRule {
276
+	p := &model.AddressBookCollectionRule{}
277
+	global.DB.Where("type = ? and to_id = ? and collection_id = ?", model.ShareAddressBookRuleTypePersonal, toid, cid).First(p)
278
+	return p
279
+}
280
+func (s *AddressBookService) CreateRule(t *model.AddressBookCollectionRule) error {
281
+	return global.DB.Create(t).Error
282
+}
283
+
284
+func (s *AddressBookService) ListRules(page uint, size uint, f func(tx *gorm.DB)) *model.AddressBookCollectionRuleList {
285
+	res := &model.AddressBookCollectionRuleList{}
286
+	res.Page = int64(page)
287
+	res.PageSize = int64(size)
288
+	tx := global.DB.Model(&model.AddressBookCollectionRule{})
289
+	if f != nil {
290
+		f(tx)
291
+	}
292
+	tx.Count(&res.Total)
293
+	tx.Scopes(Paginate(page, size))
294
+	tx.Find(&res.AddressBookCollectionRule)
295
+	return res
296
+}
297
+
298
+func (s *AddressBookService) UpdateRule(t *model.AddressBookCollectionRule) error {
299
+	return global.DB.Model(t).Updates(t).Error
300
+}
301
+
302
+func (s *AddressBookService) DeleteRule(t *model.AddressBookCollectionRule) error {
303
+	return global.DB.Delete(t).Error
304
+}
305
+
306
+// CheckCollectionOwner 检查Collection的所有者
307
+func (s *AddressBookService) CheckCollectionOwner(uid uint, cid uint) bool {
308
+	p := s.CollectionInfoById(cid)
309
+	return p.UserId == uid
310
+}

+ 14 - 9
service/tag.go

@@ -14,9 +14,9 @@ func (s *TagService) Info(id uint) *model.Tag {
14 14
 	global.DB.Where("id = ?", id).First(p)
15 15
 	return p
16 16
 }
17
-func (s *TagService) InfoByUserIdAndName(userid uint, name string) *model.Tag {
17
+func (s *TagService) InfoByUserIdAndNameAndCollectionId(userid uint, name string, cid uint) *model.Tag {
18 18
 	p := &model.Tag{}
19
-	global.DB.Where("user_id = ? and name = ?", userid, name).First(p)
19
+	global.DB.Where("user_id = ? and name = ? and collection_id = ?", userid, name, cid).First(p)
20 20
 	return p
21 21
 }
22 22
 
@@ -26,7 +26,12 @@ func (s *TagService) ListByUserId(userId uint) (res *model.TagList) {
26 26
 	})
27 27
 	return
28 28
 }
29
-
29
+func (s *TagService) ListByUserIdAndCollectionId(userId, cid uint) (res *model.TagList) {
30
+	res = s.List(1, 1000, func(tx *gorm.DB) {
31
+		tx.Where("user_id = ? and collection_id = ?", userId, cid)
32
+	})
33
+	return
34
+}
30 35
 func (s *TagService) UpdateTags(userId uint, tags map[string]uint) {
31 36
 	tx := global.DB.Begin()
32 37
 	//先查询所有tag
@@ -58,13 +63,13 @@ func (s *TagService) UpdateTags(userId uint, tags map[string]uint) {
58 63
 }
59 64
 
60 65
 // InfoById 根据用户id取用户信息
61
-func (t *TagService) InfoById(id uint) *model.Tag {
66
+func (s *TagService) InfoById(id uint) *model.Tag {
62 67
 	u := &model.Tag{}
63 68
 	global.DB.Where("id = ?", id).First(u)
64 69
 	return u
65 70
 }
66 71
 
67
-func (t *TagService) List(page, pageSize uint, where func(tx *gorm.DB)) (res *model.TagList) {
72
+func (s *TagService) List(page, pageSize uint, where func(tx *gorm.DB)) (res *model.TagList) {
68 73
 	res = &model.TagList{}
69 74
 	res.Page = int64(page)
70 75
 	res.PageSize = int64(pageSize)
@@ -79,15 +84,15 @@ func (t *TagService) List(page, pageSize uint, where func(tx *gorm.DB)) (res *mo
79 84
 }
80 85
 
81 86
 // Create 创建
82
-func (t *TagService) Create(u *model.Tag) error {
87
+func (s *TagService) Create(u *model.Tag) error {
83 88
 	res := global.DB.Create(u).Error
84 89
 	return res
85 90
 }
86
-func (t *TagService) Delete(u *model.Tag) error {
91
+func (s *TagService) Delete(u *model.Tag) error {
87 92
 	return global.DB.Delete(u).Error
88 93
 }
89 94
 
90 95
 // Update 更新
91
-func (t *TagService) Update(u *model.Tag) error {
92
-	return global.DB.Model(u).Updates(u).Error
96
+func (s *TagService) Update(u *model.Tag) error {
97
+	return global.DB.Model(u).Select("*").Omit("created_at").Updates(u).Error
93 98
 }

+ 5 - 0
service/user.go

@@ -101,6 +101,11 @@ func (us *UserService) List(page, pageSize uint, where func(tx *gorm.DB)) (res *
101 101
 	return
102 102
 }
103 103
 
104
+func (us *UserService) ListByIds(ids []uint) (res []*model.User) {
105
+	global.DB.Where("id in ?", ids).Find(&res)
106
+	return res
107
+}
108
+
104 109
 // ListByGroupId 根据组id取用户列表
105 110
 func (us *UserService) ListByGroupId(groupId, page, pageSize uint) (res *model.UserList) {
106 111
 	res = us.List(page, pageSize, func(tx *gorm.DB) {

+ 18 - 0
utils/tools.go

@@ -73,3 +73,21 @@ func RandomString(n int) string {
73 73
 	}
74 74
 	return string(b)
75 75
 }
76
+
77
+// Keys 泛型函数,K 是键类型,V 是值类型
78
+func Keys[K comparable, V any](m map[K]V) []K {
79
+	keys := make([]K, 0, len(m))
80
+	for k := range m {
81
+		keys = append(keys, k)
82
+	}
83
+	return keys
84
+}
85
+
86
+// Values 泛型函数,K 是键类型,V 是值类型
87
+func Values[K comparable, V any](m map[K]V) []V {
88
+	values := make([]V, 0, len(m))
89
+	for _, v := range m {
90
+		values = append(values, v)
91
+	}
92
+	return values
93
+}