mirror of
https://github.com/go-gitea/gitea.git
synced 2026-07-27 02:56:25 +00:00
This PR replaces a set of struct-based `Get` lookups with explicit `db.Get` / `db.Exist` conditions in places where zero-value fields can lead to ambiguous matches or incorrect records being returned. The main goal is to make read paths deterministic and avoid accidentally matching the wrong row when only part of a struct is populated. ### What changed - replace many `db.GetEngine(ctx).Get(bean)` calls with explicit `builder.Eq` conditions across models such as actions, admin tasks, issues, pull requests, repositories, users, packages, redirects, watches, stars, and follows - use quoted column names where needed for reserved fields like `index`, `type`, and `name` - add dedicated user lookup helpers for: - primary email - OAuth login source / login name - update sign-in and OAuth-related flows to use explicit individual-user lookups instead of partially populated `User` structs - tighten package property and Terraform lock lookups to avoid ambiguous reads and updates - keep existing fallback behavior where needed, while removing reliance on zero-value struct matching ### User-facing impact These changes primarily affect authentication and account lookup paths: - email/username sign-in now re-fetches users through explicit keys - OAuth2 auto-linking now resolves users by name or primary email explicitly - OAuth2 login/sync now looks up users by login source, login type, and login name explicitly - non-individual accounts are no longer implicitly matched through partial user lookups in these flows This should reduce the risk of incorrect account matches and make query behavior more predictable across the codebase. --------- Co-authored-by: bircni <bircni@icloud.com>
126 lines
3.3 KiB
Go
126 lines
3.3 KiB
Go
// Copyright 2016 The Gogs Authors. All rights reserved.
|
|
// Copyright 2018 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package repo
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"gitea.dev/models/db"
|
|
"gitea.dev/modules/log"
|
|
"gitea.dev/modules/timeutil"
|
|
"gitea.dev/modules/util"
|
|
|
|
"xorm.io/builder"
|
|
)
|
|
|
|
// ErrMirrorNotExist mirror does not exist error
|
|
var ErrMirrorNotExist = util.NewNotExistErrorf("Mirror does not exist")
|
|
|
|
// Mirror represents mirror information of a repository.
|
|
type Mirror struct {
|
|
ID int64 `xorm:"pk autoincr"`
|
|
RepoID int64 `xorm:"INDEX"`
|
|
Repo *Repository `xorm:"-"`
|
|
Interval time.Duration
|
|
EnablePrune bool `xorm:"NOT NULL DEFAULT true"`
|
|
|
|
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX"`
|
|
NextUpdateUnix timeutil.TimeStamp `xorm:"INDEX"`
|
|
LastSyncUnix timeutil.TimeStamp `xorm:"INDEX"`
|
|
|
|
LFS bool `xorm:"lfs_enabled NOT NULL DEFAULT false"`
|
|
LFSEndpoint string `xorm:"lfs_endpoint TEXT"`
|
|
|
|
RemoteAddress string `xorm:"VARCHAR(2048)"`
|
|
}
|
|
|
|
func init() {
|
|
db.RegisterModel(new(Mirror))
|
|
}
|
|
|
|
// BeforeInsert will be invoked by XORM before inserting a record
|
|
func (m *Mirror) BeforeInsert() {
|
|
if m != nil {
|
|
m.UpdatedUnix = timeutil.TimeStampNow()
|
|
m.NextUpdateUnix = timeutil.TimeStampNow()
|
|
}
|
|
}
|
|
|
|
// GetRepository returns the repository.
|
|
func (m *Mirror) GetRepository(ctx context.Context) *Repository {
|
|
if m.Repo != nil {
|
|
return m.Repo
|
|
}
|
|
var err error
|
|
m.Repo, err = GetRepositoryByID(ctx, m.RepoID)
|
|
if err != nil {
|
|
log.Error("getRepositoryByID[%d]: %v", m.ID, err)
|
|
}
|
|
return m.Repo
|
|
}
|
|
|
|
// GetRemoteName returns the name of the remote.
|
|
func (m *Mirror) GetRemoteName() string {
|
|
return "origin"
|
|
}
|
|
|
|
// ScheduleNextUpdate calculates and sets next update time.
|
|
func (m *Mirror) ScheduleNextUpdate() {
|
|
if m.Interval != 0 {
|
|
m.NextUpdateUnix = timeutil.TimeStampNow().AddDuration(m.Interval)
|
|
} else {
|
|
m.NextUpdateUnix = 0
|
|
}
|
|
}
|
|
|
|
// GetMirrorByRepoID returns mirror information of a repository.
|
|
func GetMirrorByRepoID(ctx context.Context, repoID int64) (*Mirror, error) {
|
|
m, has, err := db.Get[Mirror](ctx, builder.Eq{"repo_id": repoID})
|
|
if err != nil {
|
|
return nil, err
|
|
} else if !has {
|
|
return nil, ErrMirrorNotExist
|
|
}
|
|
return m, nil
|
|
}
|
|
|
|
// UpdateMirror updates the mirror
|
|
func UpdateMirror(ctx context.Context, m *Mirror) error {
|
|
_, err := db.GetEngine(ctx).ID(m.ID).AllCols().Update(m)
|
|
return err
|
|
}
|
|
|
|
// TouchMirror updates the mirror updatedUnix
|
|
func TouchMirror(ctx context.Context, m *Mirror) error {
|
|
m.UpdatedUnix = timeutil.TimeStampNow()
|
|
_, err := db.GetEngine(ctx).ID(m.ID).Cols("updated_unix").Update(m)
|
|
return err
|
|
}
|
|
|
|
// DeleteMirrorByRepoID deletes a mirror by repoID
|
|
func DeleteMirrorByRepoID(ctx context.Context, repoID int64) error {
|
|
_, err := db.GetEngine(ctx).Delete(&Mirror{RepoID: repoID})
|
|
return err
|
|
}
|
|
|
|
// MirrorsIterate iterates all mirror repositories.
|
|
func MirrorsIterate(ctx context.Context, limit int, f func(idx int, bean any) error) error {
|
|
sess := db.GetEngine(ctx).
|
|
Where("next_update_unix<=?", time.Now().Unix()).
|
|
And("next_update_unix!=0").
|
|
OrderBy("updated_unix ASC")
|
|
if limit > 0 {
|
|
sess = sess.Limit(limit)
|
|
}
|
|
return sess.Iterate(new(Mirror), f)
|
|
}
|
|
|
|
// InsertMirror inserts a mirror to database
|
|
func InsertMirror(ctx context.Context, mirror *Mirror) error {
|
|
_, err := db.GetEngine(ctx).Insert(mirror)
|
|
return err
|
|
}
|