@@ -16,38 +16,51 @@ import (
1616 user_model "code.gitea.io/gitea/models/user"
1717 "code.gitea.io/gitea/modules/secret"
1818 "code.gitea.io/gitea/modules/setting"
19- "code.gitea.io/gitea/modules/timeutil"
2019 "code.gitea.io/gitea/modules/util"
2120
2221 "golang.org/x/crypto/ssh"
2322)
2423
2524// UserSSHKeypair represents an SSH keypair for repository mirroring
2625type UserSSHKeypair struct {
27- ID int64 `xorm:"pk autoincr"`
28- OwnerID int64 `xorm:"INDEX NOT NULL"`
29- PrivateKeyEncrypted string `xorm:"TEXT NOT NULL"`
30- PublicKey string `xorm:"TEXT NOT NULL"`
31- Fingerprint string `xorm:"VARCHAR(255) UNIQUE NOT NULL"`
32- CreatedUnix timeutil.TimeStamp `xorm:"created"`
33- UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
26+ OwnerID int64
27+ PrivateKeyEncrypted string
28+ PublicKey string
29+ Fingerprint string
3430}
3531
36- func init () {
37- db .RegisterModel (new (UserSSHKeypair ))
38- }
39-
40- // GetUserSSHKeypairByOwner gets the most recent SSH keypair for the given owner
32+ // GetUserSSHKeypairByOwner gets the SSH keypair for the given owner
4133func GetUserSSHKeypairByOwner (ctx context.Context , ownerID int64 ) (* UserSSHKeypair , error ) {
42- keypair := & UserSSHKeypair {}
43- has , err := db .GetEngine (ctx ).Where ("owner_id = ?" , ownerID ).
44- Desc ("created_unix" ).Get (keypair )
34+ settings , err := user_model .GetSettings (ctx , ownerID , []string {
35+ user_model .UserSSHMirrorPrivPem ,
36+ user_model .UserSSHMirrorPubPem ,
37+ user_model .UserSSHMirrorFingerprint ,
38+ })
4539 if err != nil {
4640 return nil , err
4741 }
48- if ! has {
42+ if len ( settings ) == 0 {
4943 return nil , util .NewNotExistErrorf ("SSH keypair does not exist for owner %d" , ownerID )
5044 }
45+
46+ keypair := & UserSSHKeypair {
47+ OwnerID : ownerID ,
48+ }
49+
50+ if privSetting , exists := settings [user_model .UserSSHMirrorPrivPem ]; exists {
51+ keypair .PrivateKeyEncrypted = privSetting .SettingValue
52+ }
53+ if pubSetting , exists := settings [user_model .UserSSHMirrorPubPem ]; exists {
54+ keypair .PublicKey = pubSetting .SettingValue
55+ }
56+ if fpSetting , exists := settings [user_model .UserSSHMirrorFingerprint ]; exists {
57+ keypair .Fingerprint = fpSetting .SettingValue
58+ }
59+
60+ if keypair .PrivateKeyEncrypted == "" || keypair .PublicKey == "" || keypair .Fingerprint == "" {
61+ return nil , util .NewNotExistErrorf ("SSH keypair incomplete for owner %d" , ownerID )
62+ }
63+
5164 return keypair , nil
5265}
5366
@@ -73,14 +86,30 @@ func CreateUserSSHKeypair(ctx context.Context, ownerID int64) (*UserSSHKeypair,
7386 return nil , fmt .Errorf ("failed to encrypt private key: %w" , err )
7487 }
7588
89+ err = db .WithTx (ctx , func (ctx context.Context ) error {
90+ if err := user_model .SetUserSetting (ctx , ownerID , user_model .UserSSHMirrorPrivPem , privateKeyEncrypted ); err != nil {
91+ return fmt .Errorf ("failed to save private key: %w" , err )
92+ }
93+ if err := user_model .SetUserSetting (ctx , ownerID , user_model .UserSSHMirrorPubPem , publicKeyStr ); err != nil {
94+ return fmt .Errorf ("failed to save public key: %w" , err )
95+ }
96+ if err := user_model .SetUserSetting (ctx , ownerID , user_model .UserSSHMirrorFingerprint , fingerprintStr ); err != nil {
97+ return fmt .Errorf ("failed to save fingerprint: %w" , err )
98+ }
99+ return nil
100+ })
101+ if err != nil {
102+ return nil , err
103+ }
104+
76105 keypair := & UserSSHKeypair {
77106 OwnerID : ownerID ,
78107 PrivateKeyEncrypted : privateKeyEncrypted ,
79108 PublicKey : publicKeyStr ,
80109 Fingerprint : fingerprintStr ,
81110 }
82111
83- return keypair , db . Insert ( ctx , keypair )
112+ return keypair , nil
84113}
85114
86115// GetDecryptedPrivateKey returns the decrypted private key
@@ -115,12 +144,29 @@ func (k *UserSSHKeypair) GetPublicKeyWithComment(ctx context.Context) (string, e
115144
116145// DeleteUserSSHKeypair deletes an SSH keypair
117146func DeleteUserSSHKeypair (ctx context.Context , ownerID int64 ) error {
118- _ , err := db .GetEngine (ctx ).Where ("owner_id = ?" , ownerID ).Delete (& UserSSHKeypair {})
119- return err
147+ return db .WithTx (ctx , func (ctx context.Context ) error {
148+ if err := user_model .DeleteUserSetting (ctx , ownerID , user_model .UserSSHMirrorPrivPem ); err != nil {
149+ return err
150+ }
151+ if err := user_model .DeleteUserSetting (ctx , ownerID , user_model .UserSSHMirrorPubPem ); err != nil {
152+ return err
153+ }
154+ return user_model .DeleteUserSetting (ctx , ownerID , user_model .UserSSHMirrorFingerprint )
155+ })
120156}
121157
122158// RegenerateUserSSHKeypair regenerates an SSH keypair for the given owner
123159func RegenerateUserSSHKeypair (ctx context.Context , ownerID int64 ) (* UserSSHKeypair , error ) {
124- // TODO: This creates a new one old ones will be garbage collected later, as the user may accidentally regenerate
125- return CreateUserSSHKeypair (ctx , ownerID )
160+ var keypair * UserSSHKeypair
161+ err := db .WithTx (ctx , func (ctx context.Context ) error {
162+ _ = DeleteUserSSHKeypair (ctx , ownerID )
163+
164+ newKeypair , err := CreateUserSSHKeypair (ctx , ownerID )
165+ if err != nil {
166+ return err
167+ }
168+ keypair = newKeypair
169+ return nil
170+ })
171+ return keypair , err
126172}
0 commit comments