1
1
package v1
2
2
3
3
import (
4
+ "context"
4
5
"crypto/rsa"
5
6
"fmt"
6
7
"net/http"
8
+ "os"
7
9
"strconv"
8
10
11
+ "github.com/actiontech/sqle/sqle/errors"
9
12
"github.com/actiontech/sqle/sqle/utils"
10
13
"github.com/go-git/go-git/v5/plumbing"
11
14
"github.com/go-git/go-git/v5/plumbing/storer"
@@ -15,6 +18,11 @@ import (
15
18
16
19
"github.com/actiontech/sqle/sqle/model"
17
20
21
+ goGit "github.com/go-git/go-git/v5"
22
+ "github.com/go-git/go-git/v5/plumbing/transport"
23
+ goGitTransport "github.com/go-git/go-git/v5/plumbing/transport/http"
24
+
25
+ sshTransport "github.com/go-git/go-git/v5/plumbing/transport/ssh"
18
26
"github.com/labstack/echo/v4"
19
27
"golang.org/x/crypto/ssh"
20
28
)
@@ -442,7 +450,7 @@ func testGitConnectionV1(c echo.Context) error {
442
450
if err := controller .BindAndValidateReq (c , request ); err != nil {
443
451
return controller .JSONBaseErrorReq (c , err )
444
452
}
445
- repository , _ , cleanup , err := utils . CloneGitRepository (c .Request ().Context (), request .GitHttpUrl , request .GitUserName , request .GitUserPassword )
453
+ repository , _ , cleanup , err := CloneGitRepository (c .Request ().Context (), request .GitHttpUrl , request .GitUserName , request .GitUserPassword , "" )
446
454
if err != nil {
447
455
return c .JSON (http .StatusOK , & TestGitConnectionResV1 {
448
456
BaseRes : controller .NewBaseReq (nil ),
@@ -469,6 +477,15 @@ func testGitConnectionV1(c echo.Context) error {
469
477
})
470
478
}
471
479
branches , err := getBranches (references )
480
+ if err != nil {
481
+ return c .JSON (http .StatusOK , & TestGitConnectionResV1 {
482
+ BaseRes : controller .NewBaseReq (nil ),
483
+ Data : TestGitConnectionResDataV1 {
484
+ IsConnectedSuccess : false ,
485
+ ErrorMessage : err .Error (),
486
+ },
487
+ })
488
+ }
472
489
return c .JSON (http .StatusOK , & TestGitConnectionResV1 {
473
490
BaseRes : controller .NewBaseReq (nil ),
474
491
Data : TestGitConnectionResDataV1 {
@@ -478,6 +495,82 @@ func testGitConnectionV1(c echo.Context) error {
478
495
})
479
496
}
480
497
498
+ func CloneGitRepository (ctx context.Context , url , username , password , branch string ) (repository * goGit.Repository , directory string , cleanup func () error , err error ) {
499
+ // 创建一个临时目录用于存放克隆的仓库
500
+ directory , err = os .MkdirTemp ("./" , "git-repo-" )
501
+ if err != nil {
502
+ return nil , "" , nil , err
503
+ }
504
+ // 定义清理函数,用于删除临时目录
505
+ cleanup = func () error {
506
+ return os .RemoveAll (directory )
507
+ }
508
+
509
+ cloneOpts := & goGit.CloneOptions {
510
+ URL : url ,
511
+ }
512
+ // TODO use branch name to clone single branch on the repo
513
+ // if branch != "" {
514
+ // cloneOpts.ReferenceName = plumbing.ReferenceName(branch)
515
+ // }
516
+ ep , err := transport .NewEndpoint (url )
517
+ if err != nil {
518
+ return nil , "" , nil , err
519
+ }
520
+
521
+ switch {
522
+ case ep .Protocol == "http" || ep .Protocol == "https" :
523
+ // http协议下:
524
+ // 1. 账号密码登录
525
+ // username/password
526
+ // 2. token 方式
527
+ // 对于 GitLab/github,用户名可以是任意非空字符串,建议填oauth2
528
+ // gitlab:
529
+ // oauth2/token
530
+ // github:
531
+ // oauth2/token
532
+
533
+ cloneOpts .Auth = & goGitTransport.BasicAuth {
534
+ Username : username ,
535
+ Password : password ,
536
+ }
537
+ case ep .Protocol == "ssh" :
538
+ // ssh 协议
539
+ // 前置条件:
540
+ // 1. 生成密钥
541
+ // 2. 查看公钥
542
+ // 3. 仓库配置密钥
543
+ // 不支持该步骤,用户手动执行
544
+ storage := model .GetStorage ()
545
+ privateKey , exists , err := storage .GetSystemVariableByKey (model .SystemVariableSSHPrimaryKey )
546
+ if err != nil {
547
+ return nil , directory , cleanup , err
548
+ }
549
+ if ! exists {
550
+ return nil , directory , cleanup , errors .New (errors .DataNotExist , fmt .Errorf ("git ssh private key not found" ))
551
+ }
552
+ publicKeys , err := sshTransport .NewPublicKeys ("git" , []byte (privateKey .Value ), "" )
553
+ if err != nil {
554
+ return nil , directory , cleanup , fmt .Errorf ("failed to load SSH key: %w" , err )
555
+ }
556
+ publicKeys .HostKeyCallback = ssh .InsecureIgnoreHostKey ()
557
+ cloneOpts .Auth = publicKeys
558
+ case ep .Protocol == "git" :
559
+ // git协议
560
+ // 不需要校验权限
561
+ // case IsFile TODO
562
+ default :
563
+ return nil , "" , cleanup , errors .New (errors .DataInvalid , fmt .Errorf ("url is not a git url" ))
564
+ }
565
+
566
+ repository , err = goGit .PlainCloneContext (ctx , directory , false , cloneOpts )
567
+ if err != nil {
568
+ return nil , directory , cleanup , err
569
+ }
570
+
571
+ return repository , directory , cleanup , nil
572
+ }
573
+
481
574
func getBranches (references storer.ReferenceIter ) ([]string , error ) {
482
575
branches := make ([]string , 0 )
483
576
err := references .ForEach (func (ref * plumbing.Reference ) error {
@@ -558,18 +651,24 @@ type SSHPublicKeyInfo struct {
558
651
// @Tags configuration
559
652
// @Id getSSHPublicKey
560
653
// @Security ApiKeyAuth
561
- // @Success 200 {object} v1.SSHPublicKeyInfo
654
+ // @Success 200 {object} v1.SSHPublicKeyInfoV1Rsp
562
655
// @Router /v1/configurations/ssh_key [get]
563
656
func GetSSHPublicKey (c echo.Context ) error {
564
657
storage := model .GetStorage ()
565
658
systemVariables , exists , err := storage .GetSystemVariableByKey (model .SystemVariableSSHPrimaryKey )
566
659
if err != nil {
567
- c .Logger ().Errorf ("failed to get ssh public key: %v" , err )
568
660
return controller .JSONBaseErrorReq (c , err )
569
661
}
662
+ if ! exists {
663
+ return c .JSON (http .StatusOK , SSHPublicKeyInfoV1Rsp {
664
+ BaseRes : controller .NewBaseReq (nil ),
665
+ Data : SSHPublicKeyInfo {
666
+ PublicKey : "" ,
667
+ },
668
+ })
669
+ }
570
670
privateKey , err := ssh .ParseRawPrivateKey ([]byte (systemVariables .Value ))
571
671
if err != nil {
572
- c .Logger ().Errorf ("failed to parse SSH private key: %v" , err )
573
672
return controller .JSONBaseErrorReq (c , err )
574
673
}
575
674
rsaPrivateKey , ok := privateKey .(* rsa.PrivateKey )
@@ -584,12 +683,7 @@ func GetSSHPublicKey(c echo.Context) error {
584
683
return c .JSON (http .StatusOK ,
585
684
SSHPublicKeyInfoV1Rsp {
586
685
Data : SSHPublicKeyInfo {
587
- PublicKey : func () string {
588
- if ! exists {
589
- return ""
590
- }
591
- return publicKeyStr
592
- }(),
686
+ PublicKey : publicKeyStr ,
593
687
},
594
688
})
595
689
}
0 commit comments