`DeleteByID`

jc/db-migrate-orgs
Joe Chen 2023-11-03 22:22:21 -04:00
parent a44928493d
commit ac636b53cf
No known key found for this signature in database
GPG Key ID: 0BDE5280C552FF60
5 changed files with 48 additions and 38 deletions

View File

@ -5,46 +5,12 @@
package db
import (
"context"
"fmt"
"xorm.io/builder"
"xorm.io/xorm"
)
// deleteBeans deletes all given beans, beans should contain delete conditions.
func deleteBeans(e Engine, beans ...any) (err error) {
for i := range beans {
if _, err = e.Delete(beans[i]); err != nil {
return err
}
}
return nil
}
// DeleteOrganization completely and permanently deletes everything of organization.
func DeleteOrganization(org *User) error {
err := Users.DeleteByID(context.TODO(), org.ID, false)
if err != nil {
return err
}
sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
return err
}
if err = deleteBeans(sess,
&Team{OrgID: org.ID},
&OrgUser{OrgID: org.ID},
&TeamUser{OrgID: org.ID},
); err != nil {
return fmt.Errorf("deleteBeans: %v", err)
}
return sess.Commit()
}
func getOrgsByUserID(sess *xorm.Session, userID int64, showAll bool) ([]*User, error) {
orgs := make([]*User, 0, 10)
if !showAll {

View File

@ -40,6 +40,9 @@ type OrganizationsStore interface {
CountByUser(ctx context.Context, userID int64) (int64, error)
// Count returns the total number of organizations.
Count(ctx context.Context) int64
// DeleteByID deletes the given organization and all their resources. It returns
// ErrOrganizationOwnRepos when the user still has repository ownership.
DeleteByID(ctx context.Context, orgID int64) error
// AddMember adds a new member to the given organization.
AddMember(ctx context.Context, orgID, userID int64) error
@ -541,6 +544,37 @@ func (db *organizations) Count(ctx context.Context) int64 {
return count
}
type ErrOrganizationOwnRepos struct {
args errutil.Args
}
// IsErrOrganizationOwnRepos returns true if the underlying error has the type
// ErrOrganizationOwnRepos.
func IsErrOrganizationOwnRepos(err error) bool {
return errors.As(errors.Cause(err), &ErrOrganizationOwnRepos{})
}
func (err ErrOrganizationOwnRepos) Error() string {
return fmt.Sprintf("organization still has repository ownership: %v", err.args)
}
func (db *organizations) DeleteByID(ctx context.Context, orgID int64) error {
return db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
for _, t := range []any{&Team{}, &OrgUser{}, &TeamUser{}} {
err := tx.Where("org_id = ?", orgID).Delete(t).Error
if err != nil {
return errors.Wrapf(err, "clean up table %T", t)
}
}
err := NewUsersStore(tx).DeleteByID(ctx, orgID, false)
if err != nil {
return errors.Wrap(err, "delete organization")
}
return nil
})
}
var _ errutil.NotFound = (*ErrTeamNotExist)(nil)
type ErrTeamNotExist struct {

View File

@ -1791,6 +1791,16 @@ func DeleteRepository(ownerID, repoID int64) error {
return nil
}
// deleteBeans deletes all given beans, beans should contain delete conditions.
func deleteBeans(e Engine, beans ...any) (err error) {
for i := range beans {
if _, err = e.Delete(beans[i]); err != nil {
return err
}
}
return nil
}
// GetRepositoryByRef returns a Repository specified by a GFM reference.
// See https://help.github.com/articles/writing-on-github#references for more information on the syntax.
func GetRepositoryByRef(ref string) (*Repository, error) {

View File

@ -467,8 +467,7 @@ type ErrUserOwnRepos struct {
// IsErrUserOwnRepos returns true if the underlying error has the type
// ErrUserOwnRepos.
func IsErrUserOwnRepos(err error) bool {
_, ok := errors.Cause(err).(ErrUserOwnRepos)
return ok
return errors.As(errors.Cause(err), &ErrUserOwnRepos{})
}
func (err ErrUserOwnRepos) Error() string {

View File

@ -115,8 +115,9 @@ func SettingsDelete(c *context.Context) {
return
}
if err := db.DeleteOrganization(org); err != nil {
if db.IsErrUserOwnRepos(err) {
err := db.Organizations.DeleteByID(c.Req.Context(), org.ID)
if err != nil {
if db.IsErrOrganizationOwnRepos(err) {
c.Flash.Error(c.Tr("form.org_still_own_repo"))
c.Redirect(c.Org.OrgLink + "/settings/delete")
} else {