mirror of
https://github.com/go-gitea/gitea
synced 2025-07-23 10:48:37 +00:00
Merge branch 'master' into feat/approval-new
# Conflicts: # models/migrations/migrations.go
This commit is contained in:
@@ -185,6 +185,8 @@ var migrations = []Migration{
|
||||
// v65 -> v66
|
||||
NewMigration("add u2f", addU2FReg),
|
||||
// v66 -> v67
|
||||
NewMigration("add login source id column for public_key table", addLoginSourceIDToPublicKeyTable),
|
||||
// v67 -> v68
|
||||
NewMigration("add review", addReview),
|
||||
}
|
||||
|
||||
|
22
models/migrations/v66.go
Normal file
22
models/migrations/v66.go
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2017 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
func addLoginSourceIDToPublicKeyTable(x *xorm.Engine) error {
|
||||
type PublicKey struct {
|
||||
LoginSourceID int64 `xorm:"NOT NULL DEFAULT 0"`
|
||||
}
|
||||
|
||||
if err := x.Sync2(new(PublicKey)); err != nil {
|
||||
return fmt.Errorf("Sync2: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
@@ -152,6 +152,10 @@ const (
|
||||
SearchOrderBySizeReverse = "size DESC"
|
||||
SearchOrderByID = "id ASC"
|
||||
SearchOrderByIDReverse = "id DESC"
|
||||
SearchOrderByStars = "num_stars ASC"
|
||||
SearchOrderByStarsReverse = "num_stars DESC"
|
||||
SearchOrderByForks = "num_forks ASC"
|
||||
SearchOrderByForksReverse = "num_forks DESC"
|
||||
)
|
||||
|
||||
// SearchRepositoryByName takes keyword and part of repository name to search,
|
||||
|
@@ -47,13 +47,14 @@ const (
|
||||
|
||||
// PublicKey represents a user or deploy SSH public key.
|
||||
type PublicKey struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
OwnerID int64 `xorm:"INDEX NOT NULL"`
|
||||
Name string `xorm:"NOT NULL"`
|
||||
Fingerprint string `xorm:"NOT NULL"`
|
||||
Content string `xorm:"TEXT NOT NULL"`
|
||||
Mode AccessMode `xorm:"NOT NULL DEFAULT 2"`
|
||||
Type KeyType `xorm:"NOT NULL DEFAULT 1"`
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
OwnerID int64 `xorm:"INDEX NOT NULL"`
|
||||
Name string `xorm:"NOT NULL"`
|
||||
Fingerprint string `xorm:"NOT NULL"`
|
||||
Content string `xorm:"TEXT NOT NULL"`
|
||||
Mode AccessMode `xorm:"NOT NULL DEFAULT 2"`
|
||||
Type KeyType `xorm:"NOT NULL DEFAULT 1"`
|
||||
LoginSourceID int64 `xorm:"NOT NULL DEFAULT 0"`
|
||||
|
||||
CreatedUnix util.TimeStamp `xorm:"created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"updated"`
|
||||
@@ -391,7 +392,7 @@ func addKey(e Engine, key *PublicKey) (err error) {
|
||||
}
|
||||
|
||||
// AddPublicKey adds new public key to database and authorized_keys file.
|
||||
func AddPublicKey(ownerID int64, name, content string) (*PublicKey, error) {
|
||||
func AddPublicKey(ownerID int64, name, content string, LoginSourceID int64) (*PublicKey, error) {
|
||||
log.Trace(content)
|
||||
|
||||
fingerprint, err := calcFingerprint(content)
|
||||
@@ -420,12 +421,13 @@ func AddPublicKey(ownerID int64, name, content string) (*PublicKey, error) {
|
||||
}
|
||||
|
||||
key := &PublicKey{
|
||||
OwnerID: ownerID,
|
||||
Name: name,
|
||||
Fingerprint: fingerprint,
|
||||
Content: content,
|
||||
Mode: AccessModeWrite,
|
||||
Type: KeyTypeUser,
|
||||
OwnerID: ownerID,
|
||||
Name: name,
|
||||
Fingerprint: fingerprint,
|
||||
Content: content,
|
||||
Mode: AccessModeWrite,
|
||||
Type: KeyTypeUser,
|
||||
LoginSourceID: LoginSourceID,
|
||||
}
|
||||
if err = addKey(sess, key); err != nil {
|
||||
return nil, fmt.Errorf("addKey: %v", err)
|
||||
@@ -471,6 +473,14 @@ func ListPublicKeys(uid int64) ([]*PublicKey, error) {
|
||||
Find(&keys)
|
||||
}
|
||||
|
||||
// ListPublicLdapSSHKeys returns a list of synchronized public ldap ssh keys belongs to given user and login source.
|
||||
func ListPublicLdapSSHKeys(uid int64, LoginSourceID int64) ([]*PublicKey, error) {
|
||||
keys := make([]*PublicKey, 0, 5)
|
||||
return keys, x.
|
||||
Where("owner_id = ? AND login_source_id = ?", uid, LoginSourceID).
|
||||
Find(&keys)
|
||||
}
|
||||
|
||||
// UpdatePublicKeyUpdated updates public key use time.
|
||||
func UpdatePublicKeyUpdated(id int64) error {
|
||||
// Check if key exists before update as affected rows count is unreliable
|
||||
|
138
models/user.go
138
models/user.go
@@ -1272,7 +1272,7 @@ func GetUser(user *User) (bool, error) {
|
||||
type SearchUserOptions struct {
|
||||
Keyword string
|
||||
Type UserType
|
||||
OrderBy string
|
||||
OrderBy SearchOrderBy
|
||||
Page int
|
||||
PageSize int // Can be smaller than or equal to setting.UI.ExplorePagingNum
|
||||
IsActive util.OptionalBool
|
||||
@@ -1322,7 +1322,7 @@ func SearchUsers(opts *SearchUserOptions) (users []*User, _ int64, _ error) {
|
||||
users = make([]*User, 0, opts.PageSize)
|
||||
return users, count, x.Where(cond).
|
||||
Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).
|
||||
OrderBy(opts.OrderBy).
|
||||
OrderBy(opts.OrderBy.String()).
|
||||
Find(&users)
|
||||
}
|
||||
|
||||
@@ -1356,6 +1356,119 @@ func GetWatchedRepos(userID int64, private bool) ([]*Repository, error) {
|
||||
return repos, nil
|
||||
}
|
||||
|
||||
// deleteKeysMarkedForDeletion returns true if ssh keys needs update
|
||||
func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
|
||||
// Start session
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
if err := sess.Begin(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Delete keys marked for deletion
|
||||
var sshKeysNeedUpdate bool
|
||||
for _, KeyToDelete := range keys {
|
||||
key, err := SearchPublicKeyByContent(KeyToDelete)
|
||||
if err != nil {
|
||||
log.Error(4, "SearchPublicKeyByContent: %v", err)
|
||||
continue
|
||||
}
|
||||
if err = deletePublicKeys(sess, key.ID); err != nil {
|
||||
log.Error(4, "deletePublicKeys: %v", err)
|
||||
continue
|
||||
}
|
||||
sshKeysNeedUpdate = true
|
||||
}
|
||||
|
||||
if err := sess.Commit(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return sshKeysNeedUpdate, nil
|
||||
}
|
||||
|
||||
func addLdapSSHPublicKeys(s *LoginSource, usr *User, SSHPublicKeys []string) bool {
|
||||
var sshKeysNeedUpdate bool
|
||||
for _, sshKey := range SSHPublicKeys {
|
||||
if strings.HasPrefix(strings.ToLower(sshKey), "ssh") {
|
||||
sshKeyName := fmt.Sprintf("%s-%s", s.Name, sshKey[0:40])
|
||||
if _, err := AddPublicKey(usr.ID, sshKeyName, sshKey, s.ID); err != nil {
|
||||
log.Error(4, "addLdapSSHPublicKeys[%s]: Error adding LDAP Public SSH Key for user %s: %v", s.Name, usr.Name, err)
|
||||
} else {
|
||||
log.Trace("addLdapSSHPublicKeys[%s]: Added LDAP Public SSH Key for user %s", s.Name, usr.Name)
|
||||
sshKeysNeedUpdate = true
|
||||
}
|
||||
} else {
|
||||
log.Warn("addLdapSSHPublicKeys[%s]: Skipping invalid LDAP Public SSH Key for user %s: %v", s.Name, usr.Name, sshKey)
|
||||
}
|
||||
}
|
||||
return sshKeysNeedUpdate
|
||||
}
|
||||
|
||||
func synchronizeLdapSSHPublicKeys(s *LoginSource, SSHPublicKeys []string, usr *User) bool {
|
||||
var sshKeysNeedUpdate bool
|
||||
|
||||
log.Trace("synchronizeLdapSSHPublicKeys[%s]: Handling LDAP Public SSH Key synchronization for user %s", s.Name, usr.Name)
|
||||
|
||||
// Get Public Keys from DB with current LDAP source
|
||||
var giteaKeys []string
|
||||
keys, err := ListPublicLdapSSHKeys(usr.ID, s.ID)
|
||||
if err != nil {
|
||||
log.Error(4, "synchronizeLdapSSHPublicKeys[%s]: Error listing LDAP Public SSH Keys for user %s: %v", s.Name, usr.Name, err)
|
||||
}
|
||||
|
||||
for _, v := range keys {
|
||||
giteaKeys = append(giteaKeys, v.OmitEmail())
|
||||
}
|
||||
|
||||
// Get Public Keys from LDAP and skip duplicate keys
|
||||
var ldapKeys []string
|
||||
for _, v := range SSHPublicKeys {
|
||||
ldapKey := strings.Join(strings.Split(v, " ")[:2], " ")
|
||||
if !util.ExistsInSlice(ldapKey, ldapKeys) {
|
||||
ldapKeys = append(ldapKeys, ldapKey)
|
||||
}
|
||||
}
|
||||
|
||||
// Check if Public Key sync is needed
|
||||
if util.IsEqualSlice(giteaKeys, ldapKeys) {
|
||||
log.Trace("synchronizeLdapSSHPublicKeys[%s]: LDAP Public Keys are already in sync for %s (LDAP:%v/DB:%v)", s.Name, usr.Name, len(ldapKeys), len(giteaKeys))
|
||||
return false
|
||||
}
|
||||
log.Trace("synchronizeLdapSSHPublicKeys[%s]: LDAP Public Key needs update for user %s (LDAP:%v/DB:%v)", s.Name, usr.Name, len(ldapKeys), len(giteaKeys))
|
||||
|
||||
// Add LDAP Public SSH Keys that doesn't already exist in DB
|
||||
var newLdapSSHKeys []string
|
||||
for _, LDAPPublicSSHKey := range ldapKeys {
|
||||
if !util.ExistsInSlice(LDAPPublicSSHKey, giteaKeys) {
|
||||
newLdapSSHKeys = append(newLdapSSHKeys, LDAPPublicSSHKey)
|
||||
}
|
||||
}
|
||||
if addLdapSSHPublicKeys(s, usr, newLdapSSHKeys) {
|
||||
sshKeysNeedUpdate = true
|
||||
}
|
||||
|
||||
// Mark LDAP keys from DB that doesn't exist in LDAP for deletion
|
||||
var giteaKeysToDelete []string
|
||||
for _, giteaKey := range giteaKeys {
|
||||
if !util.ExistsInSlice(giteaKey, ldapKeys) {
|
||||
log.Trace("synchronizeLdapSSHPublicKeys[%s]: Marking LDAP Public SSH Key for deletion for user %s: %v", s.Name, usr.Name, giteaKey)
|
||||
giteaKeysToDelete = append(giteaKeysToDelete, giteaKey)
|
||||
}
|
||||
}
|
||||
|
||||
// Delete LDAP keys from DB that doesn't exist in LDAP
|
||||
needUpd, err := deleteKeysMarkedForDeletion(giteaKeysToDelete)
|
||||
if err != nil {
|
||||
log.Error(4, "synchronizeLdapSSHPublicKeys[%s]: Error deleting LDAP Public SSH Keys marked for deletion for user %s: %v", s.Name, usr.Name, err)
|
||||
}
|
||||
if needUpd {
|
||||
sshKeysNeedUpdate = true
|
||||
}
|
||||
|
||||
return sshKeysNeedUpdate
|
||||
}
|
||||
|
||||
// SyncExternalUsers is used to synchronize users with external authorization source
|
||||
func SyncExternalUsers() {
|
||||
if !taskStatusTable.StartIfNotRunning(syncExternalUsers) {
|
||||
@@ -1377,10 +1490,13 @@ func SyncExternalUsers() {
|
||||
if !s.IsActived || !s.IsSyncEnabled {
|
||||
continue
|
||||
}
|
||||
|
||||
if s.IsLDAP() {
|
||||
log.Trace("Doing: SyncExternalUsers[%s]", s.Name)
|
||||
|
||||
var existingUsers []int64
|
||||
var isAttributeSSHPublicKeySet = len(strings.TrimSpace(s.LDAP().AttributeSSHPublicKey)) > 0
|
||||
var sshKeysNeedUpdate bool
|
||||
|
||||
// Find all users with this login type
|
||||
var users []User
|
||||
@@ -1389,7 +1505,6 @@ func SyncExternalUsers() {
|
||||
Find(&users)
|
||||
|
||||
sr := s.LDAP().SearchEntries()
|
||||
|
||||
for _, su := range sr {
|
||||
if len(su.Username) == 0 {
|
||||
continue
|
||||
@@ -1426,11 +1541,23 @@ func SyncExternalUsers() {
|
||||
}
|
||||
|
||||
err = CreateUser(usr)
|
||||
|
||||
if err != nil {
|
||||
log.Error(4, "SyncExternalUsers[%s]: Error creating user %s: %v", s.Name, su.Username, err)
|
||||
} else if isAttributeSSHPublicKeySet {
|
||||
log.Trace("SyncExternalUsers[%s]: Adding LDAP Public SSH Keys for user %s", s.Name, usr.Name)
|
||||
if addLdapSSHPublicKeys(s, usr, su.SSHPublicKey) {
|
||||
sshKeysNeedUpdate = true
|
||||
}
|
||||
}
|
||||
} else if updateExisting {
|
||||
existingUsers = append(existingUsers, usr.ID)
|
||||
|
||||
// Synchronize SSH Public Key if that attribute is set
|
||||
if isAttributeSSHPublicKeySet && synchronizeLdapSSHPublicKeys(s, su.SSHPublicKey, usr) {
|
||||
sshKeysNeedUpdate = true
|
||||
}
|
||||
|
||||
// Check if user data has changed
|
||||
if (len(s.LDAP().AdminFilter) > 0 && usr.IsAdmin != su.IsAdmin) ||
|
||||
strings.ToLower(usr.Email) != strings.ToLower(su.Mail) ||
|
||||
@@ -1455,6 +1582,11 @@ func SyncExternalUsers() {
|
||||
}
|
||||
}
|
||||
|
||||
// Rewrite authorized_keys file if LDAP Public SSH Key attribute is set and any key was added or removed
|
||||
if sshKeysNeedUpdate {
|
||||
RewriteAllPublicKeys()
|
||||
}
|
||||
|
||||
// Deactivate users not present in LDAP
|
||||
if updateExisting {
|
||||
for _, usr := range users {
|
||||
|
Reference in New Issue
Block a user