mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-29 10:57:44 +09:00 
			
		
		
		
	#3281 fix x.Iterate returns nothing inside session scope with SQLite3
This commit is contained in:
		| @@ -5,12 +5,10 @@ | ||||
| package models | ||||
|  | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"encoding/base64" | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"math/big" | ||||
| 	"os" | ||||
| @@ -24,6 +22,7 @@ import ( | ||||
| 	"github.com/go-xorm/xorm" | ||||
| 	"golang.org/x/crypto/ssh" | ||||
|  | ||||
| 	"github.com/gogits/gogs/modules/base" | ||||
| 	"github.com/gogits/gogs/modules/log" | ||||
| 	"github.com/gogits/gogs/modules/process" | ||||
| 	"github.com/gogits/gogs/modules/setting" | ||||
| @@ -457,96 +456,20 @@ func ListPublicKeys(uid int64) ([]*PublicKey, error) { | ||||
| 	return keys, x.Where("owner_id = ?", uid).Find(&keys) | ||||
| } | ||||
|  | ||||
| // rewriteAuthorizedKeys finds and deletes corresponding line in authorized_keys file. | ||||
| func rewriteAuthorizedKeys(key *PublicKey, p, tmpP string) error { | ||||
| 	fr, err := os.Open(p) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer fr.Close() | ||||
|  | ||||
| 	fw, err := os.OpenFile(tmpP, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer fw.Close() | ||||
|  | ||||
| 	isFound := false | ||||
| 	keyword := fmt.Sprintf("key-%d", key.ID) | ||||
| 	buf := bufio.NewReader(fr) | ||||
| 	for { | ||||
| 		line, errRead := buf.ReadString('\n') | ||||
| 		line = strings.TrimSpace(line) | ||||
|  | ||||
| 		if errRead != nil { | ||||
| 			if errRead != io.EOF { | ||||
| 				return errRead | ||||
| 			} | ||||
|  | ||||
| 			// Reached end of file, if nothing to read then break, | ||||
| 			// otherwise handle the last line. | ||||
| 			if len(line) == 0 { | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// Found the line and copy rest of file. | ||||
| 		if !isFound && strings.Contains(line, keyword) && strings.Contains(line, key.Content) { | ||||
| 			isFound = true | ||||
| 			continue | ||||
| 		} | ||||
| 		// Still finding the line, copy the line that currently read. | ||||
| 		if _, err = fw.WriteString(line + "\n"); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		if errRead == io.EOF { | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if !isFound { | ||||
| 		log.Warn("SSH key %d not found in authorized_keys file for deletion", key.ID) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // UpdatePublicKey updates given public key. | ||||
| func UpdatePublicKey(key *PublicKey) error { | ||||
| 	_, err := x.Id(key.ID).AllCols().Update(key) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func deletePublicKey(e *xorm.Session, keyID int64) error { | ||||
| 	sshOpLocker.Lock() | ||||
| 	defer sshOpLocker.Unlock() | ||||
|  | ||||
| 	key := &PublicKey{ID: keyID} | ||||
| 	has, err := e.Get(key) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} else if !has { | ||||
| // deletePublicKeys does the actual key deletion but does not update authorized_keys file. | ||||
| func deletePublicKeys(e *xorm.Session, keyIDs ...int64) error { | ||||
| 	if len(keyIDs) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	if _, err = e.Id(key.ID).Delete(new(PublicKey)); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// Don't need to rewrite this file if builtin SSH server is enabled. | ||||
| 	if setting.SSH.StartBuiltinServer { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	fpath := filepath.Join(setting.SSH.RootPath, "authorized_keys") | ||||
| 	tmpPath := fpath + ".tmp" | ||||
| 	if err = rewriteAuthorizedKeys(key, fpath, tmpPath); err != nil { | ||||
| 		return err | ||||
| 	} else if err = os.Remove(fpath); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return os.Rename(tmpPath, fpath) | ||||
| 	_, err := e.In("id", strings.Join(base.Int64sToStrings(keyIDs), ",")).Delete(new(PublicKey)) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // DeletePublicKey deletes SSH key information both in database and authorized_keys file. | ||||
| @@ -570,14 +493,20 @@ func DeletePublicKey(doer *User, id int64) (err error) { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if err = deletePublicKey(sess, id); err != nil { | ||||
| 	if err = deletePublicKeys(sess, id); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return sess.Commit() | ||||
| 	if err = sess.Commit(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return RewriteAllPublicKeys() | ||||
| } | ||||
|  | ||||
| // RewriteAllPublicKeys removes any authorized key and rewrite all keys from database again. | ||||
| // Note: x.Iterate does not get latest data after insert/delete, so we have to call this function | ||||
| // outsite any session scope independently. | ||||
| func RewriteAllPublicKeys() error { | ||||
| 	sshOpLocker.Lock() | ||||
| 	defer sshOpLocker.Unlock() | ||||
| @@ -814,7 +743,7 @@ func DeleteDeployKey(doer *User, id int64) error { | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} else if !has { | ||||
| 		if err = deletePublicKey(sess, key.KeyID); err != nil { | ||||
| 		if err = deletePublicKeys(sess, key.KeyID); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user