mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 03:25:11 +01:00 
			
		
		
		
	#3281 fix x.Iterate returns nothing inside session scope with SQLite3
This commit is contained in:
		
							parent
							
								
									4d8b905541
								
							
						
					
					
						commit
						2d76de2574
					
				| @ -3,7 +3,7 @@ Gogs - Go Git Service [ | ||||
| 
 | ||||
| ##### Current tip version: 0.9.56 (see [Releases](https://github.com/gogits/gogs/releases) for binary versions) | ||||
| ##### Current tip version: 0.9.57 (see [Releases](https://github.com/gogits/gogs/releases) for binary versions) | ||||
| 
 | ||||
| | Web | UI  | Preview  | | ||||
| |:-------------:|:-------:|:-------:| | ||||
|  | ||||
							
								
								
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							| @ -17,7 +17,7 @@ import ( | ||||
| 	"github.com/gogits/gogs/modules/setting" | ||||
| ) | ||||
| 
 | ||||
| const APP_VER = "0.9.56.0726" | ||||
| const APP_VER = "0.9.57.0726" | ||||
| 
 | ||||
| func init() { | ||||
| 	runtime.GOMAXPROCS(runtime.NumCPU()) | ||||
|  | ||||
| @ -27,9 +27,10 @@ type Engine interface { | ||||
| 	Exec(string, ...interface{}) (sql.Result, error) | ||||
| 	Find(interface{}, ...interface{}) error | ||||
| 	Get(interface{}) (bool, error) | ||||
| 	Id(interface{}) *xorm.Session | ||||
| 	Insert(...interface{}) (int64, error) | ||||
| 	InsertOne(interface{}) (int64, error) | ||||
| 	Id(interface{}) *xorm.Session | ||||
| 	Iterate(interface{}, xorm.IterFunc) error | ||||
| 	Sql(string, ...interface{}) *xorm.Session | ||||
| 	Where(string, ...interface{}) *xorm.Session | ||||
| } | ||||
|  | ||||
| @ -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 | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @ -768,10 +768,13 @@ func deleteUser(e *xorm.Session, u *User) error { | ||||
| 	if err = e.Find(&keys, &PublicKey{OwnerID: u.ID}); err != nil { | ||||
| 		return fmt.Errorf("get all public keys: %v", err) | ||||
| 	} | ||||
| 	for _, key := range keys { | ||||
| 		if err = deletePublicKey(e, key.ID); err != nil { | ||||
| 			return fmt.Errorf("deletePublicKey: %v", err) | ||||
| 		} | ||||
| 
 | ||||
| 	keyIDs := make([]int64, len(keys)) | ||||
| 	for i := range keys { | ||||
| 		keyIDs[i] = keys[i].ID | ||||
| 	} | ||||
| 	if err = deletePublicKeys(e, keyIDs...); err != nil { | ||||
| 		return fmt.Errorf("deletePublicKeys: %v", err) | ||||
| 	} | ||||
| 	// ***** END: PublicKey ***** | ||||
| 
 | ||||
| @ -788,7 +791,6 @@ func deleteUser(e *xorm.Session, u *User) error { | ||||
| 	// Note: There are something just cannot be roll back, | ||||
| 	//	so just keep error logs of those operations. | ||||
| 
 | ||||
| 	RewriteAllPublicKeys() | ||||
| 	os.RemoveAll(UserPath(u.Name)) | ||||
| 	os.Remove(u.CustomAvatarPath()) | ||||
| 
 | ||||
| @ -809,15 +811,20 @@ func DeleteUser(u *User) (err error) { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return sess.Commit() | ||||
| 	if err = sess.Commit(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return RewriteAllPublicKeys() | ||||
| } | ||||
| 
 | ||||
| // DeleteInactivateUsers deletes all inactivate users and email addresses. | ||||
| func DeleteInactivateUsers() (err error) { | ||||
| 	users := make([]*User, 0, 10) | ||||
| 	if err = x.Where("is_active=?", false).Find(&users); err != nil { | ||||
| 	if err = x.Where("is_active = ?", false).Find(&users); err != nil { | ||||
| 		return fmt.Errorf("get all inactive users: %v", err) | ||||
| 	} | ||||
| 	// FIXME: should only update authorized_keys file once after all deletions. | ||||
| 	for _, u := range users { | ||||
| 		if err = DeleteUser(u); err != nil { | ||||
| 			// Ignore users that were set inactive by admin. | ||||
| @ -828,7 +835,7 @@ func DeleteInactivateUsers() (err error) { | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	_, err = x.Where("is_activated=?", false).Delete(new(EmailAddress)) | ||||
| 	_, err = x.Where("is_activated = ?", false).Delete(new(EmailAddress)) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| 0.9.56.0726 | ||||
| 0.9.57.0726 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user