#3281 fix x.Iterate returns nothing inside session scope with SQLite3
This commit is contained in:
parent
4d8b905541
commit
2d76de2574
6 changed files with 35 additions and 98 deletions
|
@ -3,7 +3,7 @@ Gogs - Go Git Service [![Build Status](https://travis-ci.org/gogits/gogs.svg?bra
|
||||||
|
|
||||||
![](https://github.com/gogits/gogs/blob/master/public/img/gogs-large-resize.png?raw=true)
|
![](https://github.com/gogits/gogs/blob/master/public/img/gogs-large-resize.png?raw=true)
|
||||||
|
|
||||||
##### 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 |
|
| Web | UI | Preview |
|
||||||
|:-------------:|:-------:|:-------:|
|
|:-------------:|:-------:|:-------:|
|
||||||
|
|
2
gogs.go
2
gogs.go
|
@ -17,7 +17,7 @@ import (
|
||||||
"github.com/gogits/gogs/modules/setting"
|
"github.com/gogits/gogs/modules/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
const APP_VER = "0.9.56.0726"
|
const APP_VER = "0.9.57.0726"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||||
|
|
|
@ -27,9 +27,10 @@ type Engine interface {
|
||||||
Exec(string, ...interface{}) (sql.Result, error)
|
Exec(string, ...interface{}) (sql.Result, error)
|
||||||
Find(interface{}, ...interface{}) error
|
Find(interface{}, ...interface{}) error
|
||||||
Get(interface{}) (bool, error)
|
Get(interface{}) (bool, error)
|
||||||
|
Id(interface{}) *xorm.Session
|
||||||
Insert(...interface{}) (int64, error)
|
Insert(...interface{}) (int64, error)
|
||||||
InsertOne(interface{}) (int64, error)
|
InsertOne(interface{}) (int64, error)
|
||||||
Id(interface{}) *xorm.Session
|
Iterate(interface{}, xorm.IterFunc) error
|
||||||
Sql(string, ...interface{}) *xorm.Session
|
Sql(string, ...interface{}) *xorm.Session
|
||||||
Where(string, ...interface{}) *xorm.Session
|
Where(string, ...interface{}) *xorm.Session
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,10 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
|
@ -24,6 +22,7 @@ import (
|
||||||
"github.com/go-xorm/xorm"
|
"github.com/go-xorm/xorm"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
|
|
||||||
|
"github.com/gogits/gogs/modules/base"
|
||||||
"github.com/gogits/gogs/modules/log"
|
"github.com/gogits/gogs/modules/log"
|
||||||
"github.com/gogits/gogs/modules/process"
|
"github.com/gogits/gogs/modules/process"
|
||||||
"github.com/gogits/gogs/modules/setting"
|
"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)
|
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.
|
// UpdatePublicKey updates given public key.
|
||||||
func UpdatePublicKey(key *PublicKey) error {
|
func UpdatePublicKey(key *PublicKey) error {
|
||||||
_, err := x.Id(key.ID).AllCols().Update(key)
|
_, err := x.Id(key.ID).AllCols().Update(key)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func deletePublicKey(e *xorm.Session, keyID int64) error {
|
// deletePublicKeys does the actual key deletion but does not update authorized_keys file.
|
||||||
sshOpLocker.Lock()
|
func deletePublicKeys(e *xorm.Session, keyIDs ...int64) error {
|
||||||
defer sshOpLocker.Unlock()
|
if len(keyIDs) == 0 {
|
||||||
|
|
||||||
key := &PublicKey{ID: keyID}
|
|
||||||
has, err := e.Get(key)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
} else if !has {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = e.Id(key.ID).Delete(new(PublicKey)); err != nil {
|
_, err := e.In("id", strings.Join(base.Int64sToStrings(keyIDs), ",")).Delete(new(PublicKey))
|
||||||
return err
|
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeletePublicKey deletes SSH key information both in database and authorized_keys file.
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = deletePublicKey(sess, id); err != nil {
|
if err = deletePublicKeys(sess, id); err != nil {
|
||||||
return err
|
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.
|
// 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 {
|
func RewriteAllPublicKeys() error {
|
||||||
sshOpLocker.Lock()
|
sshOpLocker.Lock()
|
||||||
defer sshOpLocker.Unlock()
|
defer sshOpLocker.Unlock()
|
||||||
|
@ -814,7 +743,7 @@ func DeleteDeployKey(doer *User, id int64) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if !has {
|
} else if !has {
|
||||||
if err = deletePublicKey(sess, key.KeyID); err != nil {
|
if err = deletePublicKeys(sess, key.KeyID); err != nil {
|
||||||
return err
|
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 {
|
if err = e.Find(&keys, &PublicKey{OwnerID: u.ID}); err != nil {
|
||||||
return fmt.Errorf("get all public keys: %v", err)
|
return fmt.Errorf("get all public keys: %v", err)
|
||||||
}
|
}
|
||||||
for _, key := range keys {
|
|
||||||
if err = deletePublicKey(e, key.ID); err != nil {
|
keyIDs := make([]int64, len(keys))
|
||||||
return fmt.Errorf("deletePublicKey: %v", err)
|
for i := range keys {
|
||||||
}
|
keyIDs[i] = keys[i].ID
|
||||||
|
}
|
||||||
|
if err = deletePublicKeys(e, keyIDs...); err != nil {
|
||||||
|
return fmt.Errorf("deletePublicKeys: %v", err)
|
||||||
}
|
}
|
||||||
// ***** END: PublicKey *****
|
// ***** END: PublicKey *****
|
||||||
|
|
||||||
|
@ -788,7 +791,6 @@ func deleteUser(e *xorm.Session, u *User) error {
|
||||||
// Note: There are something just cannot be roll back,
|
// Note: There are something just cannot be roll back,
|
||||||
// so just keep error logs of those operations.
|
// so just keep error logs of those operations.
|
||||||
|
|
||||||
RewriteAllPublicKeys()
|
|
||||||
os.RemoveAll(UserPath(u.Name))
|
os.RemoveAll(UserPath(u.Name))
|
||||||
os.Remove(u.CustomAvatarPath())
|
os.Remove(u.CustomAvatarPath())
|
||||||
|
|
||||||
|
@ -809,15 +811,20 @@ func DeleteUser(u *User) (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return sess.Commit()
|
if err = sess.Commit(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return RewriteAllPublicKeys()
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteInactivateUsers deletes all inactivate users and email addresses.
|
// DeleteInactivateUsers deletes all inactivate users and email addresses.
|
||||||
func DeleteInactivateUsers() (err error) {
|
func DeleteInactivateUsers() (err error) {
|
||||||
users := make([]*User, 0, 10)
|
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)
|
return fmt.Errorf("get all inactive users: %v", err)
|
||||||
}
|
}
|
||||||
|
// FIXME: should only update authorized_keys file once after all deletions.
|
||||||
for _, u := range users {
|
for _, u := range users {
|
||||||
if err = DeleteUser(u); err != nil {
|
if err = DeleteUser(u); err != nil {
|
||||||
// Ignore users that were set inactive by admin.
|
// 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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.9.56.0726
|
0.9.57.0726
|
Reference in a new issue