diff options
Diffstat (limited to 'models')
-rw-r--r-- | models/lfs.go | 80 | ||||
-rw-r--r-- | models/repo_list.go | 48 |
2 files changed, 103 insertions, 25 deletions
diff --git a/models/lfs.go b/models/lfs.go index 9b20642777..5f5fe2ccf4 100644 --- a/models/lfs.go +++ b/models/lfs.go @@ -8,6 +8,8 @@ import ( "io" "code.gitea.io/gitea/modules/timeutil" + + "xorm.io/builder" ) // LFSMetaObject stores metadata for LFS tracked files. @@ -106,19 +108,91 @@ func (repo *Repository) GetLFSMetaObjectByOid(oid string) (*LFSMetaObject, error // RemoveLFSMetaObjectByOid removes a LFSMetaObject entry from database by its OID. // It may return ErrLFSObjectNotExist or a database error. -func (repo *Repository) RemoveLFSMetaObjectByOid(oid string) error { +func (repo *Repository) RemoveLFSMetaObjectByOid(oid string) (int64, error) { if len(oid) == 0 { - return ErrLFSObjectNotExist + return 0, ErrLFSObjectNotExist } sess := x.NewSession() defer sess.Close() if err := sess.Begin(); err != nil { - return err + return -1, err } m := &LFSMetaObject{Oid: oid, RepositoryID: repo.ID} if _, err := sess.Delete(m); err != nil { + return -1, err + } + + count, err := sess.Count(&LFSMetaObject{Oid: oid}) + if err != nil { + return count, err + } + + return count, sess.Commit() +} + +// GetLFSMetaObjects returns all LFSMetaObjects associated with a repository +func (repo *Repository) GetLFSMetaObjects(page, pageSize int) ([]*LFSMetaObject, error) { + sess := x.NewSession() + defer sess.Close() + + if page >= 0 && pageSize > 0 { + start := 0 + if page > 0 { + start = (page - 1) * pageSize + } + sess.Limit(pageSize, start) + } + lfsObjects := make([]*LFSMetaObject, 0, pageSize) + return lfsObjects, sess.Find(&lfsObjects, &LFSMetaObject{RepositoryID: repo.ID}) +} + +// CountLFSMetaObjects returns a count of all LFSMetaObjects associated with a repository +func (repo *Repository) CountLFSMetaObjects() (int64, error) { + return x.Count(&LFSMetaObject{RepositoryID: repo.ID}) +} + +// LFSObjectAccessible checks if a provided Oid is accessible to the user +func LFSObjectAccessible(user *User, oid string) (bool, error) { + if user.IsAdmin { + count, err := x.Count(&LFSMetaObject{Oid: oid}) + return (count > 0), err + } + cond := accessibleRepositoryCondition(user.ID) + count, err := x.Where(cond).Join("INNER", "repository", "`lfs_meta_object`.repository_id = `repository`.id").Count(&LFSMetaObject{Oid: oid}) + return (count > 0), err +} + +// LFSAutoAssociate auto associates accessible LFSMetaObjects +func LFSAutoAssociate(metas []*LFSMetaObject, user *User, repoID int64) error { + sess := x.NewSession() + defer sess.Close() + if err := sess.Begin(); err != nil { + return err + } + + oids := make([]interface{}, len(metas)) + oidMap := make(map[string]*LFSMetaObject, len(metas)) + for i, meta := range metas { + oids[i] = meta.Oid + oidMap[meta.Oid] = meta + } + + cond := builder.NewCond() + if !user.IsAdmin { + cond = builder.In("`lfs_meta_object`.repository_id", + builder.Select("`repository`.id").From("repository").Where(accessibleRepositoryCondition(user.ID))) + } + newMetas := make([]*LFSMetaObject, 0, len(metas)) + if err := sess.Cols("oid").Where(cond).In("oid", oids...).GroupBy("oid").Find(&newMetas); err != nil { + return err + } + for i := range newMetas { + newMetas[i].Size = oidMap[newMetas[i].Oid].Size + newMetas[i].RepositoryID = repoID + } + if _, err := sess.InsertMulti(newMetas); err != nil { return err } diff --git a/models/repo_list.go b/models/repo_list.go index 692d4d002f..c823647eba 100644 --- a/models/repo_list.go +++ b/models/repo_list.go @@ -176,28 +176,7 @@ func SearchRepository(opts *SearchRepoOptions) (RepositoryList, int64, error) { if opts.Private { if !opts.UserIsAdmin && opts.UserID != 0 && opts.UserID != opts.OwnerID { // OK we're in the context of a User - // We should be Either - cond = cond.And(builder.Or( - // 1. Be able to see all non-private repositories that either: - cond.And( - builder.Eq{"is_private": false}, - builder.Or( - // A. Aren't in organisations __OR__ - builder.NotIn("owner_id", builder.Select("id").From("`user`").Where(builder.Eq{"type": UserTypeOrganization})), - // B. Isn't a private organisation. (Limited is OK because we're logged in) - builder.NotIn("owner_id", builder.Select("id").From("`user`").Where(builder.Eq{"visibility": structs.VisibleTypePrivate}))), - ), - // 2. Be able to see all repositories that we have access to - builder.In("id", builder.Select("repo_id"). - From("`access`"). - Where(builder.And( - builder.Eq{"user_id": opts.UserID}, - builder.Gt{"mode": int(AccessModeNone)}))), - // 3. Be able to see all repositories that we are in a team - builder.In("id", builder.Select("`team_repo`.repo_id"). - From("team_repo"). - Where(builder.Eq{"`team_user`.uid": opts.UserID}). - Join("INNER", "team_user", "`team_user`.team_id = `team_repo`.team_id")))) + cond = cond.And(accessibleRepositoryCondition(opts.UserID)) } } else { // Not looking at private organisations @@ -316,6 +295,31 @@ func SearchRepository(opts *SearchRepoOptions) (RepositoryList, int64, error) { return repos, count, nil } +// accessibleRepositoryCondition takes a user a returns a condition for checking if a repository is accessible +func accessibleRepositoryCondition(userID int64) builder.Cond { + return builder.Or( + // 1. Be able to see all non-private repositories that either: + builder.And( + builder.Eq{"`repository`.is_private": false}, + builder.Or( + // A. Aren't in organisations __OR__ + builder.NotIn("`repository`.owner_id", builder.Select("id").From("`user`").Where(builder.Eq{"type": UserTypeOrganization})), + // B. Isn't a private organisation. (Limited is OK because we're logged in) + builder.NotIn("`repository`.owner_id", builder.Select("id").From("`user`").Where(builder.Eq{"visibility": structs.VisibleTypePrivate}))), + ), + // 2. Be able to see all repositories that we have access to + builder.In("`repository`.id", builder.Select("repo_id"). + From("`access`"). + Where(builder.And( + builder.Eq{"user_id": userID}, + builder.Gt{"mode": int(AccessModeNone)}))), + // 3. Be able to see all repositories that we are in a team + builder.In("`repository`.id", builder.Select("`team_repo`.repo_id"). + From("team_repo"). + Where(builder.Eq{"`team_user`.uid": userID}). + Join("INNER", "team_user", "`team_user`.team_id = `team_repo`.team_id"))) +} + // SearchRepositoryByName takes keyword and part of repository name to search, // it returns results in given range and number of total results. func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, error) { |