mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 21:16:26 +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