From 67a9416ae55ea765e3f405e00d89b0b8f3899330 Mon Sep 17 00:00:00 2001 From: Unknwon Date: Thu, 12 Feb 2015 12:38:44 -0500 Subject: templates/user/auth/signin.tmpl: hide sign up prompt when registration is disabled #884 --- gogs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'gogs.go') diff --git a/gogs.go b/gogs.go index eac59362..76c6c71f 100644 --- a/gogs.go +++ b/gogs.go @@ -17,7 +17,7 @@ import ( "github.com/gogits/gogs/modules/setting" ) -const APP_VER = "0.5.13.0211 Beta" +const APP_VER = "0.5.13.0212 Beta" func init() { runtime.GOMAXPROCS(runtime.NumCPU()) -- cgit v1.2.3 From 685ed1f8075c0fedc2cfaf0f8c43f9439132e1da Mon Sep 17 00:00:00 2001 From: Unknwon Date: Sat, 14 Feb 2015 17:01:33 -0500 Subject: models: fix XORM API break cmd/web.go: check version after load config --- cmd/web.go | 3 +-- gogs.go | 2 +- models/models.go | 2 +- templates/.VERSION | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) (limited to 'gogs.go') diff --git a/cmd/web.go b/cmd/web.go index 3284acb9..4b06a882 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -166,12 +166,11 @@ func newMacaron() *macaron.Macaron { } func runWeb(ctx *cli.Context) { - checkVersion() - if ctx.IsSet("config") { setting.CustomConf = ctx.String("config") } routers.GlobalInit() + checkVersion() m := newMacaron() diff --git a/gogs.go b/gogs.go index 76c6c71f..34790b72 100644 --- a/gogs.go +++ b/gogs.go @@ -17,7 +17,7 @@ import ( "github.com/gogits/gogs/modules/setting" ) -const APP_VER = "0.5.13.0212 Beta" +const APP_VER = "0.5.13.0214 Beta" func init() { runtime.GOMAXPROCS(runtime.NumCPU()) diff --git a/models/models.go b/models/models.go index 35e80383..486aceac 100644 --- a/models/models.go +++ b/models/models.go @@ -121,7 +121,7 @@ func SetEngine() (err error) { if err != nil { return fmt.Errorf("models.init(fail to create xorm.log): %v", err) } - x.Logger = xorm.NewSimpleLogger(f) + x.SetLogger(xorm.NewSimpleLogger(f)) x.ShowSQL = true x.ShowInfo = true diff --git a/templates/.VERSION b/templates/.VERSION index 6d13155b..0c9421a4 100644 --- a/templates/.VERSION +++ b/templates/.VERSION @@ -1 +1 @@ -0.5.13.0212 Beta \ No newline at end of file +0.5.13.0214 Beta \ No newline at end of file -- cgit v1.2.3 From 1654e9ecab3923b7fe5d528fc86c1a549546bd29 Mon Sep 17 00:00:00 2001 From: Unknwon Date: Sat, 21 Feb 2015 22:13:47 -0500 Subject: templates/user/settings/emial.tmpl: little fix on UI - routers/user: little code format - conf/locale: update French locale --- conf/locale/locale_fr-CA.ini | 16 ++++---- gogs.go | 2 +- models/user.go | 9 +++-- modules/auth/user_form.go | 2 +- routers/user/auth.go | 5 +-- routers/user/setting.go | 80 ++++++++++++++++++-------------------- templates/.VERSION | 2 +- templates/user/settings/email.tmpl | 6 +-- 8 files changed, 58 insertions(+), 64 deletions(-) (limited to 'gogs.go') diff --git a/conf/locale/locale_fr-CA.ini b/conf/locale/locale_fr-CA.ini index 0aeae342..e744b9d9 100755 --- a/conf/locale/locale_fr-CA.ini +++ b/conf/locale/locale_fr-CA.ini @@ -59,8 +59,8 @@ run_user=Entrer un Utilisateur run_user_helper=L'utilisateur doit avoir accès à la Racine du Référentiel et éxécuter Gogs. domain=Domaine domain_helper=Cela affecte les doublons d'URL SSH. -http_port=HTTP Port -http_port_helper=Port number which application will listen on. +http_port=Port HTTP +http_port_helper=Numéro de port que l'application écoutera. app_url=URL de l'Application app_url_helper=Cela affecte les doublons d'URL HTTP/HTTPS et le contenu d'e-mail. email_title=Paramètres du Service de Messagerie (Facultatif) @@ -514,10 +514,10 @@ dashboard.delete_repo_archives=Supprimer toutes les archives de référentiels dashboard.delete_repo_archives_success=Toutes les archives de référentiels ont été supprimés avec succès. dashboard.git_gc_repos=Collecter les déchets des référentiels dashboard.git_gc_repos_success=Tous les référentiels ont effectué la collecte avec succès. -dashboard.resync_all_sshkeys=Rewrite '.ssh/autorized_key' file (caution: non-Gogs keys will be lost) -dashboard.resync_all_sshkeys_success=All public keys have been rewritten successfully. -dashboard.resync_all_update_hooks=Rewrite all update hook of repositories (needed when custom config path is changed) -dashboard.resync_all_update_hooks_success=All repositories' update hook have been rewritten successfully. +dashboard.resync_all_sshkeys=Ré-écrire le fichier '.ssh/autorized_key' (attention : les clés hors-Gogs vont être perdues) +dashboard.resync_all_sshkeys_success=Toutes les clés publiques ont été ré-écrites avec succès. +dashboard.resync_all_update_hooks=Ré-écrire tous les hooks de mises à jour des dépôts (requis quand le chemin de la configuration personnalisé est modifié) +dashboard.resync_all_update_hooks_success=Tous les hooks de mises à jour des dépôts ont été ré-écris avec succès. dashboard.server_uptime=Durée de Marche Serveur dashboard.current_goroutine=Goroutines actuelles @@ -638,7 +638,7 @@ config.db_path_helper=("sqlite3" uniquement) config.service_config=Configuration du Service config.register_email_confirm=Nécessite une confirmation par courriel config.disable_register=Désactiver l'Enregistrement -config.show_registration_button=Show Register Button +config.show_registration_button=Afficher le bouton d'enregistrement config.require_sign_in_view=Connexion Obligatoire pour Visualiser config.mail_notify=Mailer les Notifications config.enable_cache_avatar=Activer le Cache d'Avatar @@ -647,7 +647,7 @@ config.reset_password_code_lives=Réinitialiser le Mot De Passe des Limites de C config.webhook_config=Configuration Webhook config.task_interval=Intervalles de Tâches config.deliver_timeout=Expiration d'Envoi -config.skip_tls_verify=Skip TLS Verify +config.skip_tls_verify=Ne pas vérifier TLS config.mailer_config=Configuration du Maileur config.mailer_enabled=Activé config.mailer_name=Nom diff --git a/gogs.go b/gogs.go index 34790b72..5c24e229 100644 --- a/gogs.go +++ b/gogs.go @@ -17,7 +17,7 @@ import ( "github.com/gogits/gogs/modules/setting" ) -const APP_VER = "0.5.13.0214 Beta" +const APP_VER = "0.5.14.0221 Beta" func init() { runtime.GOMAXPROCS(runtime.NumCPU()) diff --git a/models/user.go b/models/user.go index 2da0881c..9f9b0cd7 100644 --- a/models/user.go +++ b/models/user.go @@ -627,7 +627,7 @@ func GetUserIdsByNames(names []string) []int64 { return ids } -// Get all email addresses +// GetEmailAddresses returns all e-mail addresses belongs to given user. func GetEmailAddresses(uid int64) ([]*EmailAddress, error) { emails := make([]*EmailAddress, 0, 5) err := x.Where("uid=?", uid).Find(&emails) @@ -641,7 +641,6 @@ func GetEmailAddresses(uid int64) ([]*EmailAddress, error) { } isPrimaryFound := false - for _, email := range emails { if email.Email == u.Email { isPrimaryFound = true @@ -654,7 +653,11 @@ func GetEmailAddresses(uid int64) ([]*EmailAddress, error) { // We alway want the primary email address displayed, even if it's not in // the emailaddress table (yet) if !isPrimaryFound { - emails = append(emails, &EmailAddress{Email: u.Email, IsActivated: true, IsPrimary: true}) + emails = append(emails, &EmailAddress{ + Email: u.Email, + IsActivated: true, + IsPrimary: true, + }) } return emails, nil } diff --git a/modules/auth/user_form.go b/modules/auth/user_form.go index 3c0ff651..b616a460 100644 --- a/modules/auth/user_form.go +++ b/modules/auth/user_form.go @@ -99,7 +99,7 @@ func (f *UploadAvatarForm) Validate(ctx *macaron.Context, errs binding.Errors) b } type AddEmailForm struct { - Email string `form:"email" binding:"Required;Email;MaxSize(50)"` + Email string `binding:"Required;Email;MaxSize(50)"` } func (f *AddEmailForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { diff --git a/routers/user/auth.go b/routers/user/auth.go index 9ed44e35..5dacaf8c 100644 --- a/routers/user/auth.go +++ b/routers/user/auth.go @@ -351,15 +351,12 @@ func ActivateEmail(ctx *middleware.Context) { // Verify code. if email := models.VerifyActiveEmailCode(code, email_string); email != nil { - err := email.Activate() - if err != nil { + if err := email.Activate(); err != nil { ctx.Handle(500, "ActivateEmail", err) } log.Trace("Email activated: %s", email.Email) - ctx.Flash.Success(ctx.Tr("settings.activate_email_success")) - } ctx.Redirect(setting.AppSubUrl + "/user/settings/email") diff --git a/routers/user/setting.go b/routers/user/setting.go index 953e6113..9398f69a 100644 --- a/routers/user/setting.go +++ b/routers/user/setting.go @@ -133,13 +133,12 @@ func SettingsEmails(ctx *middleware.Context) { ctx.Data["PageIsUserSettings"] = true ctx.Data["PageIsSettingsEmails"] = true - var err error - ctx.Data["Emails"], err = models.GetEmailAddresses(ctx.User.Id) - + emails, err := models.GetEmailAddresses(ctx.User.Id) if err != nil { - ctx.Handle(500, "email.GetEmailAddresses", err) + ctx.Handle(500, "GetEmailAddresses", err) return } + ctx.Data["Emails"] = emails ctx.HTML(200, SETTINGS_EMAILS) } @@ -149,16 +148,16 @@ func SettingsEmailPost(ctx *middleware.Context, form auth.AddEmailForm) { ctx.Data["PageIsUserSettings"] = true ctx.Data["PageIsSettingsEmails"] = true - var err error - ctx.Data["Emails"], err = models.GetEmailAddresses(ctx.User.Id) + emails, err := models.GetEmailAddresses(ctx.User.Id) if err != nil { - ctx.Handle(500, "email.GetEmailAddresses", err) + ctx.Handle(500, "GetEmailAddresses", err) return } + ctx.Data["Emails"] = emails - // Delete Email address. + // Delete E-mail address. if ctx.Query("_method") == "DELETE" { - id := com.StrTo(ctx.Query("id")).MustInt64() + id := ctx.QueryInt64("id") if id <= 0 { return } @@ -174,7 +173,7 @@ func SettingsEmailPost(ctx *middleware.Context, form auth.AddEmailForm) { // Make emailaddress primary. if ctx.Query("_method") == "PRIMARY" { - id := com.StrTo(ctx.Query("id")).MustInt64() + id := ctx.QueryInt64("id") if id <= 0 { return } @@ -189,46 +188,41 @@ func SettingsEmailPost(ctx *middleware.Context, form auth.AddEmailForm) { } // Add Email address. - if ctx.Req.Method == "POST" { - if ctx.HasError() { - ctx.HTML(200, SETTINGS_EMAILS) - return - } + if ctx.HasError() { + ctx.HTML(200, SETTINGS_EMAILS) + return + } - cleanEmail := strings.Replace(form.Email, "\n", "", -1) - e := &models.EmailAddress{ - Uid: ctx.User.Id, - Email: cleanEmail, - IsActivated: !setting.Service.RegisterEmailConfirm, - } + cleanEmail := strings.Replace(form.Email, "\n", "", -1) + e := &models.EmailAddress{ + Uid: ctx.User.Id, + Email: cleanEmail, + IsActivated: !setting.Service.RegisterEmailConfirm, + } - if err := models.AddEmailAddress(e); err != nil { - if err == models.ErrEmailAlreadyUsed { - ctx.RenderWithErr(ctx.Tr("form.email_has_been_used"), SETTINGS_EMAILS, &form) - return - } - ctx.Handle(500, "email.AddEmailAddress", err) + if err := models.AddEmailAddress(e); err != nil { + if err == models.ErrEmailAlreadyUsed { + ctx.RenderWithErr(ctx.Tr("form.email_been_used"), SETTINGS_EMAILS, &form) return - } else { - - // Send confirmation e-mail - if setting.Service.RegisterEmailConfirm { - mailer.SendActivateEmail(ctx.Render, ctx.User, e) + } + ctx.Handle(500, "AddEmailAddress", err) + return + } else { + // Send confirmation e-mail + if setting.Service.RegisterEmailConfirm { + mailer.SendActivateEmail(ctx.Render, ctx.User, e) - if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { - log.Error(4, "Set cache(MailResendLimit) fail: %v", err) - } - ctx.Flash.Success(ctx.Tr("settings.add_email_success_confirmation_email_sent")) - } else { - ctx.Flash.Success(ctx.Tr("settings.add_email_success")) + if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil { + log.Error(4, "Set cache(MailResendLimit) fail: %v", err) } - - log.Trace("Email address added: %s", e.Email) - - ctx.Redirect(setting.AppSubUrl + "/user/settings/email") - return + ctx.Flash.Success(ctx.Tr("settings.add_email_success_confirmation_email_sent")) + } else { + ctx.Flash.Success(ctx.Tr("settings.add_email_success")) } + log.Trace("Email address added: %s", e.Email) + ctx.Redirect(setting.AppSubUrl + "/user/settings/email") + return } ctx.HTML(200, SETTINGS_EMAILS) diff --git a/templates/.VERSION b/templates/.VERSION index 0c9421a4..489addf9 100644 --- a/templates/.VERSION +++ b/templates/.VERSION @@ -1 +1 @@ -0.5.13.0214 Beta \ No newline at end of file +0.5.14.0221 Beta \ No newline at end of file diff --git a/templates/user/settings/email.tmpl b/templates/user/settings/email.tmpl index c99e6a04..ec152c5d 100644 --- a/templates/user/settings/email.tmpl +++ b/templates/user/settings/email.tmpl @@ -16,7 +16,7 @@ {{range .Emails}} -- cgit v1.2.3 From c753fdceaf0549aa865cff4e1f42be5d907bbdb1 Mon Sep 17 00:00:00 2001 From: Unknwon Date: Sun, 22 Feb 2015 03:07:04 -0500 Subject: templates/org/home.tmpl: fix org member can't see public repo --- gogs.go | 2 +- templates/.VERSION | 2 +- templates/org/home.tmpl | 140 ++++++++++++++++++++++++------------------------ 3 files changed, 72 insertions(+), 72 deletions(-) (limited to 'gogs.go') diff --git a/gogs.go b/gogs.go index 5c24e229..b2366b63 100644 --- a/gogs.go +++ b/gogs.go @@ -17,7 +17,7 @@ import ( "github.com/gogits/gogs/modules/setting" ) -const APP_VER = "0.5.14.0221 Beta" +const APP_VER = "0.5.14.0222 Beta" func init() { runtime.GOMAXPROCS(runtime.NumCPU()) diff --git a/templates/.VERSION b/templates/.VERSION index 489addf9..b9cd4a18 100644 --- a/templates/.VERSION +++ b/templates/.VERSION @@ -1 +1 @@ -0.5.14.0221 Beta \ No newline at end of file +0.5.14.0222 Beta \ No newline at end of file diff --git a/templates/org/home.tmpl b/templates/org/home.tmpl index bb160b57..df29d61f 100644 --- a/templates/org/home.tmpl +++ b/templates/org/home.tmpl @@ -9,85 +9,85 @@ {{if .IsOrganizationOwner}}{{end}} {{if .Org.Description}}

{{.Org.Description}}

{{end}} - +
{{$isMember := .Org.IsOrgMember $.SignedUser.Id}} -
-
- {{if .IsOrganizationOwner}} - {{.i18n.Tr "new_repo"}} - {{end}} -
-
- {{range .Repos}} - {{if .HasAccess $.SignedUser.Name}} -
-
    -
  • {{.NumStars}}
  • -
  • {{.NumForks}}
  • -
-

{{.Name}}

-

{{.Description}}

-

{{$.i18n.Tr "org.repo_updated"}} {{TimeSince .Updated $.i18n.Lang}}

-
- {{end}} +
+
+ {{if .IsOrganizationOwner}} + {{.i18n.Tr "new_repo"}} + {{end}} +
+
+ {{range .Repos}} + {{if or (not .IsPrivate) (.HasAccess $.SignedUser.Name)}} +
+
    +
  • {{.NumStars}}
  • +
  • {{.NumForks}}
  • +
+

{{.Name}}

+

{{.Description}}

+

{{$.i18n.Tr "org.repo_updated"}} {{TimeSince .Updated $.i18n.Lang}}

+
{{end}} -
+ {{end}}
-
-
-
-
- {{if $isMember}} - {{.Org.NumMembers}} - {{end}} - {{.i18n.Tr "org.people"}} -
-
- {{range .Members}} +
+
+
+
+
+ {{if $isMember}} + {{.Org.NumMembers}} + {{end}} + {{.i18n.Tr "org.people"}} +
+
+ {{range .Members}} {{if or $isMember (.IsPublicMember $.Org.Id)}} - - {{end}} + {{end}} -
- {{if .IsOrganizationOwner}} - - {{end}} -
- {{if $isMember}} -
-
-
- {{.Org.NumTeams}} - {{.i18n.Tr "org.teams"}} -
-
-
    - {{range .Teams}} -
  • - {{.Name}} -

    {{.NumMembers}} {{$.i18n.Tr "org.lower_members"}} · {{.NumRepos}} {{$.i18n.Tr "org.lower_repositories"}}

    -
  • - {{end}} -
-
- {{if .IsOrganizationOwner}} - - {{end}} -
- {{end}} + {{end}} +
+ {{if .IsOrganizationOwner}} + + {{end}}
-
+ {{if $isMember}} +
+
+
+ {{.Org.NumTeams}} + {{.i18n.Tr "org.teams"}} +
+
+
    + {{range .Teams}} +
  • + {{.Name}} +

    {{.NumMembers}} {{$.i18n.Tr "org.lower_members"}} · {{.NumRepos}} {{$.i18n.Tr "org.lower_repositories"}}

    +
  • + {{end}} +
+
+ {{if .IsOrganizationOwner}} + + {{end}} +
+ {{end}} +
+
{{template "ng/base/footer" .}} \ No newline at end of file -- cgit v1.2.3 From ee68a826a55c6a4305e7f609db57501a54a5bc47 Mon Sep 17 00:00:00 2001 From: Unknwon Date: Mon, 23 Feb 2015 02:15:53 -0500 Subject: v4 migration, merge 'dev', clean code and mirror fix --- gogs.go | 2 +- models/access.go | 37 +++-- models/action.go | 20 +-- models/migrations/migrations.go | 76 +++++++++-- models/models.go | 5 +- models/org.go | 296 ++++++++++++++++++++++++---------------- models/repo.go | 132 ++++++++---------- models/user.go | 4 +- routers/org/teams.go | 2 +- routers/repo/setting.go | 1 - templates/.VERSION | 2 +- 11 files changed, 343 insertions(+), 234 deletions(-) (limited to 'gogs.go') diff --git a/gogs.go b/gogs.go index b2366b63..58cbb1a0 100644 --- a/gogs.go +++ b/gogs.go @@ -17,7 +17,7 @@ import ( "github.com/gogits/gogs/modules/setting" ) -const APP_VER = "0.5.14.0222 Beta" +const APP_VER = "0.5.15.0223 Beta" func init() { runtime.GOMAXPROCS(runtime.NumCPU()) diff --git a/models/access.go b/models/access.go index 1e1c0114..29d1a730 100644 --- a/models/access.go +++ b/models/access.go @@ -24,21 +24,19 @@ type Access struct { Mode AccessMode } -// Return the Access a user has to a repository. Will return NoneAccess if the -// user does not have access. User can be nil! -func AccessLevel(u *User, r *Repository) (AccessMode, error) { +func accessLevel(e Engine, u *User, repo *Repository) (AccessMode, error) { mode := ACCESS_MODE_NONE - if !r.IsPrivate { + if !repo.IsPrivate { mode = ACCESS_MODE_READ } if u != nil { - if u.Id == r.OwnerId { + if u.Id == repo.OwnerId { return ACCESS_MODE_OWNER, nil } - a := &Access{UserID: u.Id, RepoID: r.Id} - if has, err := x.Get(a); !has || err != nil { + a := &Access{UserID: u.Id, RepoID: repo.Id} + if has, err := e.Get(a); !has || err != nil { return mode, err } return a.Mode, nil @@ -47,12 +45,22 @@ func AccessLevel(u *User, r *Repository) (AccessMode, error) { return mode, nil } -// HasAccess returns true if someone has the request access level. User can be nil! -func HasAccess(u *User, r *Repository, testMode AccessMode) (bool, error) { - mode, err := AccessLevel(u, r) +// AccessLevel returns the Access a user has to a repository. Will return NoneAccess if the +// user does not have access. User can be nil! +func AccessLevel(u *User, repo *Repository) (AccessMode, error) { + return accessLevel(x, u, repo) +} + +func hasAccess(e Engine, u *User, repo *Repository, testMode AccessMode) (bool, error) { + mode, err := accessLevel(e, u, repo) return testMode <= mode, err } +// HasAccess returns true if someone has the request access level. User can be nil! +func HasAccess(u *User, repo *Repository, testMode AccessMode) (bool, error) { + return hasAccess(x, u, repo, testMode) +} + // GetAccessibleRepositories finds all repositories where a user has access to, // besides his own. func (u *User) GetAccessibleRepositories() (map[*Repository]AccessMode, error) { @@ -96,7 +104,8 @@ func (repo *Repository) recalculateTeamAccesses(e Engine, mode AccessMode) error func (repo *Repository) recalculateAccesses(e Engine) error { accessMap := make(map[int64]AccessMode, 20) - // Give all collaborators write access + // FIXME: should be able to have read-only access. + // Give all collaborators write access. collaborators, err := repo.getCollaborators(e) if err != nil { return err @@ -114,9 +123,7 @@ func (repo *Repository) recalculateAccesses(e Engine) error { } for _, team := range repo.Owner.Teams { - if !(team.IsOwnerTeam() || team.HasRepository(repo)) { - continue - } else if team.IsOwnerTeam() { + if team.IsOwnerTeam() { team.Authorize = ACCESS_MODE_OWNER } @@ -129,6 +136,8 @@ func (repo *Repository) recalculateAccesses(e Engine) error { } } + // FIXME: do corss-comparison so reduce deletions and additions to the minimum? + minMode := ACCESS_MODE_READ if !repo.IsPrivate { minMode = ACCESS_MODE_WRITE diff --git a/models/action.go b/models/action.go index 9ba661f1..fee5e5e6 100644 --- a/models/action.go +++ b/models/action.go @@ -434,20 +434,20 @@ func NewRepoAction(u *User, repo *Repository) (err error) { return newRepoAction(x, u, repo) } -func transferRepoAction(e Engine, u, newUser *User, repo *Repository) (err error) { +func transferRepoAction(e Engine, actUser, oldOwner, newOwner *User, repo *Repository) (err error) { action := &Action{ - ActUserId: u.Id, - ActUserName: u.Name, - ActEmail: u.Email, + ActUserId: actUser.Id, + ActUserName: actUser.Name, + ActEmail: actUser.Email, OpType: TRANSFER_REPO, RepoId: repo.Id, - RepoUserName: newUser.Name, + RepoUserName: newOwner.Name, RepoName: repo.Name, IsPrivate: repo.IsPrivate, - Content: path.Join(repo.Owner.LowerName, repo.LowerName), + Content: path.Join(oldOwner.LowerName, repo.LowerName), } if err = notifyWatchers(e, action); err != nil { - return fmt.Errorf("notify watchers '%d/%s'", u.Id, repo.Id) + return fmt.Errorf("notify watchers '%d/%s'", actUser.Id, repo.Id) } // Remove watch for organization. @@ -457,13 +457,13 @@ func transferRepoAction(e Engine, u, newUser *User, repo *Repository) (err error } } - log.Trace("action.TransferRepoAction: %s/%s", u.Name, repo.Name) + log.Trace("action.TransferRepoAction: %s/%s", actUser.Name, repo.Name) return nil } // TransferRepoAction adds new action for transferring repository. -func TransferRepoAction(u, newUser *User, repo *Repository) (err error) { - return transferRepoAction(x, u, newUser, repo) +func TransferRepoAction(actUser, oldOwner, newOwner *User, repo *Repository) (err error) { + return transferRepoAction(x, actUser, oldOwner, newOwner, repo) } // GetFeeds returns action list of given user in given context. diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index f6ef5132..25c130a9 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -53,6 +53,7 @@ var migrations = []Migration{ NewMigration("generate collaboration from access", accessToCollaboration), // V0 -> V1 NewMigration("make authorize 4 if team is owners", ownerTeamUpdate), // V1 -> V2 NewMigration("refactor access table to use id's", accessRefactor), // V2 -> V3 + NewMigration("generate team-repo from team", teamToTeamRepo), // V3 -> V4 } // Migrate database to current version @@ -214,8 +215,8 @@ func accessToCollaboration(x *xorm.Engine) (err error) { } func ownerTeamUpdate(x *xorm.Engine) (err error) { - if _, err := x.Exec("UPDATE team SET authorize=4 WHERE lower_name=?", "owners"); err != nil { - return fmt.Errorf("drop table: %v", err) + if _, err := x.Exec("UPDATE `team` SET authorize=4 WHERE lower_name=?", "owners"); err != nil { + return fmt.Errorf("update owner team table: %v", err) } return nil } @@ -239,9 +240,9 @@ func accessRefactor(x *xorm.Engine) (err error) { accessMap := make(map[UserRepo]AccessMode, 50) - results, err := x.Query("SELECT r.id as `repo_id`, r.is_private as `is_private`, r.owner_id as `owner_id`, u.type as `owner_type` FROM `repository` r LEFT JOIN user u ON r.owner_id=u.id") + results, err := x.Query("SELECT r.id AS `repo_id`, r.is_private AS `is_private`, r.owner_id AS `owner_id`, u.type AS `owner_type` FROM `repository` r LEFT JOIN `user` u ON r.owner_id=u.id") if err != nil { - return err + return fmt.Errorf("select repositories: %v", err) } for _, repo := range results { repoID := com.StrTo(repo["repo_id"]).MustInt64() @@ -249,9 +250,9 @@ func accessRefactor(x *xorm.Engine) (err error) { ownerID := com.StrTo(repo["owner_id"]).MustInt64() ownerIsOrganization := com.StrTo(repo["owner_type"]).MustInt() > 0 - results, err := x.Query("SELECT user_id FROM collaboration WHERE repo_id=?", repoID) + results, err := x.Query("SELECT `user_id` FROM `collaboration` WHERE repo_id=?", repoID) if err != nil { - return fmt.Errorf("select repos: %v", err) + return fmt.Errorf("select collaborators: %v", err) } for _, user := range results { userID := com.StrTo(user["user_id"]).MustInt64() @@ -262,6 +263,8 @@ func accessRefactor(x *xorm.Engine) (err error) { continue } + // The minimum level to add a new access record, + // because public repository has implicit open access. minAccessLevel := AccessMode(0) if !isPrivate { minAccessLevel = 1 @@ -269,7 +272,7 @@ func accessRefactor(x *xorm.Engine) (err error) { repoString := "$" + string(repo["repo_id"]) + "|" - results, err = x.Query("SELECT id, authorize, repo_ids FROM team WHERE org_id=? AND authorize > ? ORDER BY authorize ASC", ownerID, int(minAccessLevel)) + results, err = x.Query("SELECT `id`,`authorize`,`repo_ids` FROM `team` WHERE org_id=? AND authorize>? ORDER BY `authorize` ASC", ownerID, int(minAccessLevel)) if err != nil { return fmt.Errorf("select teams from org: %v", err) } @@ -281,20 +284,20 @@ func accessRefactor(x *xorm.Engine) (err error) { teamID := com.StrTo(team["id"]).MustInt64() mode := AccessMode(com.StrTo(team["authorize"]).MustInt()) - results, err := x.Query("SELECT uid FROM team_user WHERE team_id=?", teamID) + results, err := x.Query("SELECT `uid` FROM `team_user` WHERE team_id=?", teamID) if err != nil { return fmt.Errorf("select users from team: %v", err) } for _, user := range results { - userID := com.StrTo(user["uid"]).MustInt64() + userID := com.StrTo(user["user_id"]).MustInt64() accessMap[UserRepo{userID, repoID}] = mode } } } // Drop table can't be in a session (at least not in sqlite) - if _, err = x.Exec("DROP TABLE access"); err != nil { - return fmt.Errorf("drop table: %v", err) + if _, err = x.Exec("DROP TABLE `access`"); err != nil { + return fmt.Errorf("drop access table: %v", err) } // Now we start writing so we make a session @@ -313,7 +316,56 @@ func accessRefactor(x *xorm.Engine) (err error) { accesses = append(accesses, &Access{UserID: ur.UserID, RepoID: ur.RepoID, Mode: mode}) } - _, err = sess.Insert(accesses) + if _, err = sess.Insert(accesses); err != nil { + return fmt.Errorf("insert accesses: %v", err) + } + + return sess.Commit() +} + +func teamToTeamRepo(x *xorm.Engine) error { + type TeamRepo struct { + ID int64 `xorm:"pk autoincr"` + OrgID int64 `xorm:"INDEX"` + TeamID int64 `xorm:"UNIQUE(s)"` + RepoID int64 `xorm:"UNIQUE(s)"` + } + + teamRepos := make([]*TeamRepo, 0, 50) + + results, err := x.Query("SELECT `id`,`org_id`,`repo_ids` FROM `team`") + if err != nil { + return fmt.Errorf("select teams: %v", err) + } + for _, team := range results { + orgID := com.StrTo(team["org_id"]).MustInt64() + teamID := com.StrTo(team["id"]).MustInt64() + + for _, idStr := range strings.Split(string(team["repo_ids"]), "|") { + repoID := com.StrTo(strings.TrimPrefix(idStr, "$")).MustInt64() + if repoID == 0 { + continue + } + + teamRepos = append(teamRepos, &TeamRepo{ + OrgID: orgID, + TeamID: teamID, + RepoID: repoID, + }) + } + } + + sess := x.NewSession() + defer sessionRelease(sess) + if err = sess.Begin(); err != nil { + return err + } + + if err = sess.Sync2(new(TeamRepo)); err != nil { + return fmt.Errorf("sync: %v", err) + } else if _, err = sess.Insert(teamRepos); err != nil { + return fmt.Errorf("insert team-repos: %v", err) + } return sess.Commit() } diff --git a/models/models.go b/models/models.go index b0c3b897..a9436fca 100644 --- a/models/models.go +++ b/models/models.go @@ -16,7 +16,7 @@ import ( "github.com/go-xorm/xorm" _ "github.com/lib/pq" - // "github.com/gogits/gogs/models/migrations" + "github.com/gogits/gogs/models/migrations" "github.com/gogits/gogs/modules/setting" ) @@ -59,7 +59,8 @@ func init() { new(Watch), new(Star), new(Follow), new(Action), new(Issue), new(Comment), new(Attachment), new(IssueUser), new(Label), new(Milestone), new(Mirror), new(Release), new(LoginSource), new(Webhook), - new(UpdateTask), new(HookTask), new(Team), new(OrgUser), new(TeamUser), + new(UpdateTask), new(HookTask), + new(Team), new(OrgUser), new(TeamUser), new(TeamRepo), new(Notice), new(EmailAddress)) } diff --git a/models/org.go b/models/org.go index 8cb17b60..629e9345 100644 --- a/models/org.go +++ b/models/org.go @@ -6,11 +6,10 @@ package models import ( "errors" + "fmt" "os" "strings" - "github.com/Unknwon/com" - "github.com/gogits/gogs/modules/base" ) @@ -126,53 +125,48 @@ func CreateOrganization(org, owner *User) (*User, error) { org.NumMembers = 1 sess := x.NewSession() - defer sess.Close() + defer sessionRelease(sess) if err = sess.Begin(); err != nil { return nil, err } if _, err = sess.Insert(org); err != nil { - sess.Rollback() - return nil, err - } - - if err = os.MkdirAll(UserPath(org.Name), os.ModePerm); err != nil { - sess.Rollback() return nil, err } // Create default owner team. t := &Team{ - OrgId: org.Id, + OrgID: org.Id, LowerName: strings.ToLower(OWNER_TEAM), Name: OWNER_TEAM, Authorize: ACCESS_MODE_OWNER, NumMembers: 1, } if _, err = sess.Insert(t); err != nil { - sess.Rollback() return nil, err } // Add initial creator to organization and owner team. ou := &OrgUser{ Uid: owner.Id, - OrgId: org.Id, + OrgID: org.Id, IsOwner: true, NumTeams: 1, } if _, err = sess.Insert(ou); err != nil { - sess.Rollback() return nil, err } tu := &TeamUser{ Uid: owner.Id, - OrgId: org.Id, - TeamId: t.Id, + OrgID: org.Id, + TeamID: t.ID, } if _, err = sess.Insert(tu); err != nil { - sess.Rollback() + return nil, err + } + + if err = os.MkdirAll(UserPath(org.Name), os.ModePerm); err != nil { return nil, err } @@ -223,15 +217,15 @@ func DeleteOrganization(org *User) (err error) { return err } - if _, err = sess.Delete(&Team{OrgId: org.Id}); err != nil { + if _, err = sess.Delete(&Team{OrgID: org.Id}); err != nil { sess.Rollback() return err } - if _, err = sess.Delete(&OrgUser{OrgId: org.Id}); err != nil { + if _, err = sess.Delete(&OrgUser{OrgID: org.Id}); err != nil { sess.Rollback() return err } - if _, err = sess.Delete(&TeamUser{OrgId: org.Id}); err != nil { + if _, err = sess.Delete(&TeamUser{OrgID: org.Id}); err != nil { sess.Rollback() return err } @@ -247,9 +241,9 @@ func DeleteOrganization(org *User) (err error) { // OrgUser represents an organization-user relation. type OrgUser struct { - Id int64 + ID int64 `xorm:"pk autoincr"` Uid int64 `xorm:"INDEX UNIQUE(s)"` - OrgId int64 `xorm:"INDEX UNIQUE(s)"` + OrgID int64 `xorm:"INDEX UNIQUE(s)"` IsPublic bool IsOwner bool NumTeams int @@ -298,7 +292,7 @@ func ChangeOrgUserStatus(orgId, uid int64, public bool) error { } ou.IsPublic = public - _, err = x.Id(ou.Id).AllCols().Update(ou) + _, err = x.Id(ou.ID).AllCols().Update(ou) return err } @@ -316,7 +310,7 @@ func AddOrgUser(orgId, uid int64) error { ou := &OrgUser{ Uid: uid, - OrgId: orgId, + OrgID: orgId, } if _, err := sess.Insert(ou); err != nil { @@ -367,7 +361,7 @@ func RemoveOrgUser(orgId, uid int64) error { return err } - if _, err := sess.Id(ou.Id).Delete(ou); err != nil { + if _, err := sess.Id(ou.ID).Delete(ou); err != nil { sess.Rollback() return err } else if _, err = sess.Exec("UPDATE `user` SET num_members = num_members - 1 WHERE id = ?", orgId); err != nil { @@ -400,7 +394,7 @@ func RemoveOrgUser(orgId, uid int64) error { return err } for _, t := range ts { - if err = removeTeamMember(sess, org.Id, t.Id, u.Id); err != nil { + if err = removeTeamMember(sess, org.Id, t.ID, u.Id); err != nil { return err } } @@ -419,13 +413,12 @@ const OWNER_TEAM = "Owners" // Team represents a organization team. type Team struct { - Id int64 - OrgId int64 `xorm:"INDEX"` + ID int64 `xorm:"pk autoincr"` + OrgID int64 `xorm:"INDEX"` LowerName string Name string Description string Authorize AccessMode - RepoIds string `xorm:"TEXT"` Repos []*Repository `xorm:"-"` Members []*User `xorm:"-"` NumRepos int @@ -439,23 +432,20 @@ func (t *Team) IsOwnerTeam() bool { // IsTeamMember returns true if given user is a member of team. func (t *Team) IsMember(uid int64) bool { - return IsTeamMember(t.OrgId, t.Id, uid) + return IsTeamMember(t.OrgID, t.ID, uid) } -func (t *Team) getRepositories(e Engine) error { - idStrs := strings.Split(t.RepoIds, "|") - t.Repos = make([]*Repository, 0, len(idStrs)) - for _, str := range idStrs { - if len(str) == 0 { - continue - } - id := com.StrTo(str[1:]).MustInt64() - if id == 0 { - continue - } - repo, err := getRepositoryById(e, id) +func (t *Team) getRepositories(e Engine) (err error) { + teamRepos := make([]*TeamRepo, 0, t.NumRepos) + if err = x.Where("team_id=?", t.ID).Find(&teamRepos); err != nil { + return fmt.Errorf("get team-repos: %v", err) + } + + t.Repos = make([]*Repository, 0, len(teamRepos)) + for i := range teamRepos { + repo, err := getRepositoryById(e, teamRepos[i].RepoID) if err != nil { - return err + return fmt.Errorf("getRepositoryById(%d): %v", teamRepos[i].RepoID, err) } t.Repos = append(t.Repos, repo) } @@ -468,7 +458,7 @@ func (t *Team) GetRepositories() error { } func (t *Team) getMembers(e Engine) (err error) { - t.Members, err = getTeamMembers(e, t.Id) + t.Members, err = getTeamMembers(e, t.ID) return err } @@ -479,96 +469,121 @@ func (t *Team) GetMembers() (err error) { // AddMember adds new member to team of organization. func (t *Team) AddMember(uid int64) error { - return AddTeamMember(t.OrgId, t.Id, uid) + return AddTeamMember(t.OrgID, t.ID, uid) } // RemoveMember removes member from team of organization. func (t *Team) RemoveMember(uid int64) error { - return RemoveTeamMember(t.OrgId, t.Id, uid) + return RemoveTeamMember(t.OrgID, t.ID, uid) } -// AddRepository adds new repository to team of organization. -func (t *Team) AddRepository(repo *Repository) (err error) { - idStr := "$" + com.ToStr(repo.Id) + "|" - if repo.OwnerId != t.OrgId { - return errors.New("Repository not belong to organization") - } else if strings.Contains(t.RepoIds, idStr) { - return nil - } +func (t *Team) hasRepository(e Engine, repoID int64) bool { + return hasTeamRepo(e, t.OrgID, t.ID, repoID) +} - if err = repo.GetOwner(); err != nil { - return err - } else if err = t.GetMembers(); err != nil { - return err - } +// HasRepository returns true if given repository belong to team. +func (t *Team) HasRepository(repoID int64) bool { + return HasTeamRepo(t.OrgID, t.ID, repoID) +} - sess := x.NewSession() - defer sessionRelease(sess) - if err = sess.Begin(); err != nil { +func (t *Team) addRepository(e Engine, repo *Repository) (err error) { + if err = addTeamRepo(e, t.OrgID, t.ID, repo.Id); err != nil { return err } t.NumRepos++ - t.RepoIds += idStr - if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { + if _, err = e.Id(t.ID).AllCols().Update(t); err != nil { return err } - if err = repo.recalculateAccesses(sess); err != nil { + if err = repo.recalculateAccesses(e); err != nil { return err } + if err = t.getMembers(e); err != nil { + return fmt.Errorf("get team members: %v", err) + } for _, u := range t.Members { - if err = watchRepo(sess, u.Id, repo.Id, true); err != nil { + if err = watchRepo(e, u.Id, repo.Id, true); err != nil { return err } } - return sess.Commit() -} - -func (t *Team) HasRepository(repo *Repository) bool { - idStr := "$" + com.ToStr(repo.Id) + "|" - return strings.Contains(t.RepoIds, idStr) + return nil } -// RemoveRepository removes repository from team of organization. -func (t *Team) RemoveRepository(repoId int64) error { - idStr := "$" + com.ToStr(repoId) + "|" - if !strings.Contains(t.RepoIds, idStr) { +// AddRepository adds new repository to team of organization. +func (t *Team) AddRepository(repo *Repository) (err error) { + if repo.OwnerId != t.OrgID { + return errors.New("Repository does not belong to organization") + } else if t.HasRepository(repo.Id) { return nil } - repo, err := GetRepositoryById(repoId) - if err != nil { + sess := x.NewSession() + defer sessionRelease(sess) + if err = sess.Begin(); err != nil { return err } - if err = repo.GetOwner(); err != nil { - return err - } else if err = t.GetMembers(); err != nil { + if err = t.addRepository(sess, repo); err != nil { return err } - sess := x.NewSession() - defer sessionRelease(sess) - if err = sess.Begin(); err != nil { + return sess.Commit() +} + +func (t *Team) removeRepository(e Engine, repo *Repository) (err error) { + if err = removeTeamRepo(e, t.ID, repo.Id); err != nil { return err } t.NumRepos-- - t.RepoIds = strings.Replace(t.RepoIds, idStr, "", 1) - if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { + if _, err = e.Id(t.ID).AllCols().Update(t); err != nil { return err } - if err = repo.recalculateAccesses(sess); err != nil { + if err = repo.recalculateAccesses(e); err != nil { return err } + if err = t.getMembers(e); err != nil { + return fmt.Errorf("get team members: %v", err) + } for _, u := range t.Members { - if err = watchRepo(sess, u.Id, repo.Id, false); err != nil { + has, err := hasAccess(e, u, repo, ACCESS_MODE_READ) + if err != nil { return err + } else if has { + continue } + + if err = watchRepo(e, u.Id, repo.Id, false); err != nil { + return err + } + } + + return nil +} + +// RemoveRepository removes repository from team of organization. +func (t *Team) RemoveRepository(repoID int64) error { + if !t.HasRepository(repoID) { + return nil + } + + repo, err := GetRepositoryById(repoID) + if err != nil { + return err + } + + sess := x.NewSession() + defer sessionRelease(sess) + if err = sess.Begin(); err != nil { + return err + } + + if err = t.removeRepository(sess, repo); err != nil { + return err } return sess.Commit() @@ -581,7 +596,7 @@ func NewTeam(t *Team) error { return ErrTeamNameIllegal } - has, err := x.Id(t.OrgId).Get(new(User)) + has, err := x.Id(t.OrgID).Get(new(User)) if err != nil { return err } else if !has { @@ -589,7 +604,7 @@ func NewTeam(t *Team) error { } t.LowerName = strings.ToLower(t.Name) - has, err = x.Where("org_id=?", t.OrgId).And("lower_name=?", t.LowerName).Get(new(Team)) + has, err = x.Where("org_id=?", t.OrgID).And("lower_name=?", t.LowerName).Get(new(Team)) if err != nil { return err } else if has { @@ -608,7 +623,7 @@ func NewTeam(t *Team) error { } // Update organization number of teams. - if _, err = sess.Exec("UPDATE `user` SET num_teams = num_teams + 1 WHERE id = ?", t.OrgId); err != nil { + if _, err = sess.Exec("UPDATE `user` SET num_teams = num_teams + 1 WHERE id = ?", t.OrgID); err != nil { sess.Rollback() return err } @@ -617,7 +632,7 @@ func NewTeam(t *Team) error { func getTeam(e Engine, orgId int64, name string) (*Team, error) { t := &Team{ - OrgId: orgId, + OrgID: orgId, LowerName: strings.ToLower(name), } has, err := e.Get(t) @@ -667,7 +682,7 @@ func UpdateTeam(t *Team, authChanged bool) (err error) { } t.LowerName = strings.ToLower(t.Name) - if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { + if _, err = sess.Id(t.ID).AllCols().Update(t); err != nil { return err } @@ -697,7 +712,7 @@ func DeleteTeam(t *Team) error { } // Get organization. - org, err := GetUserById(t.OrgId) + org, err := GetUserById(t.OrgID) if err != nil { return err } @@ -716,16 +731,16 @@ func DeleteTeam(t *Team) error { } // Delete team-user. - if _, err = sess.Where("org_id=?", org.Id).Where("team_id=?", t.Id).Delete(new(TeamUser)); err != nil { + if _, err = sess.Where("org_id=?", org.Id).Where("team_id=?", t.ID).Delete(new(TeamUser)); err != nil { return err } // Delete team. - if _, err = sess.Id(t.Id).Delete(new(Team)); err != nil { + if _, err = sess.Id(t.ID).Delete(new(Team)); err != nil { return err } // Update organization number of teams. - if _, err = sess.Exec("UPDATE `user` SET num_teams = num_teams - 1 WHERE id = ?", t.OrgId); err != nil { + if _, err = sess.Exec("UPDATE `user` SET num_teams=num_teams-1 WHERE id=?", t.OrgID); err != nil { return err } @@ -741,20 +756,20 @@ func DeleteTeam(t *Team) error { // TeamUser represents an team-user relation. type TeamUser struct { - Id int64 - Uid int64 - OrgId int64 `xorm:"INDEX"` - TeamId int64 + ID int64 `xorm:"pk autoincr"` + OrgID int64 `xorm:"INDEX"` + TeamID int64 `xorm:"UNIQUE(s)"` + Uid int64 `xorm:"UNIQUE(s)"` } -func isTeamMember(e Engine, orgId, teamId, uid int64) bool { - has, _ := e.Where("uid=?", uid).And("org_id=?", orgId).And("team_id=?", teamId).Get(new(TeamUser)) +func isTeamMember(e Engine, orgID, teamID, uid int64) bool { + has, _ := e.Where("org_id=?", orgID).And("team_id=?", teamID).And("uid=?", uid).Get(new(TeamUser)) return has } // IsTeamMember returns true if given user is a member of team. -func IsTeamMember(orgId, teamId, uid int64) bool { - return isTeamMember(x, orgId, teamId, uid) +func IsTeamMember(orgID, teamID, uid int64) bool { + return isTeamMember(x, orgID, teamID, uid) } func getTeamMembers(e Engine, teamID int64) ([]*User, error) { @@ -777,7 +792,7 @@ func getUserTeams(e Engine, orgId, uid int64) ([]*Team, error) { ts := make([]*Team, len(tus)) for i, tu := range tus { t := new(Team) - has, err := e.Id(tu.TeamId).Get(t) + has, err := e.Id(tu.TeamID).Get(t) if err != nil { return nil, err } else if !has { @@ -822,13 +837,13 @@ func AddTeamMember(orgId, teamId, uid int64) error { tu := &TeamUser{ Uid: uid, - OrgId: orgId, - TeamId: teamId, + OrgID: orgId, + TeamID: teamId, } if _, err = sess.Insert(tu); err != nil { return err - } else if _, err = sess.Id(t.Id).Update(t); err != nil { + } else if _, err = sess.Id(t.ID).Update(t); err != nil { return err } @@ -848,7 +863,7 @@ func AddTeamMember(orgId, teamId, uid int64) error { if t.IsOwnerTeam() { ou.IsOwner = true } - if _, err = sess.Id(ou.Id).AllCols().Update(ou); err != nil { + if _, err = sess.Id(ou.ID).AllCols().Update(ou); err != nil { return err } @@ -885,13 +900,13 @@ func removeTeamMember(e Engine, orgId, teamId, uid int64) error { tu := &TeamUser{ Uid: uid, - OrgId: orgId, - TeamId: teamId, + OrgID: orgId, + TeamID: teamId, } if _, err := e.Delete(tu); err != nil { return err - } else if _, err = e.Id(t.Id).AllCols().Update(t); err != nil { + } else if _, err = e.Id(t.ID).AllCols().Update(t); err != nil { return err } @@ -912,7 +927,7 @@ func removeTeamMember(e Engine, orgId, teamId, uid int64) error { if t.IsOwnerTeam() { ou.IsOwner = false } - if _, err = e.Id(ou.Id).AllCols().Update(ou); err != nil { + if _, err = e.Id(ou.ID).AllCols().Update(ou); err != nil { return err } return nil @@ -921,13 +936,64 @@ func removeTeamMember(e Engine, orgId, teamId, uid int64) error { // RemoveTeamMember removes member from given team of given organization. func RemoveTeamMember(orgId, teamId, uid int64) error { sess := x.NewSession() - defer sess.Close() + defer sessionRelease(sess) if err := sess.Begin(); err != nil { return err } if err := removeTeamMember(sess, orgId, teamId, uid); err != nil { - sess.Rollback() return err } return sess.Commit() } + +// ___________ __________ +// \__ ___/___ _____ _____\______ \ ____ ______ ____ +// | |_/ __ \\__ \ / \| _// __ \\____ \ / _ \ +// | |\ ___/ / __ \| Y Y \ | \ ___/| |_> > <_> ) +// |____| \___ >____ /__|_| /____|_ /\___ > __/ \____/ +// \/ \/ \/ \/ \/|__| + +// TeamRepo represents an team-repository relation. +type TeamRepo struct { + ID int64 `xorm:"pk autoincr"` + OrgID int64 `xorm:"INDEX"` + TeamID int64 `xorm:"UNIQUE(s)"` + RepoID int64 `xorm:"UNIQUE(s)"` +} + +func hasTeamRepo(e Engine, orgID, teamID, repoID int64) bool { + has, _ := e.Where("org_id=?", orgID).And("team_id=?", teamID).And("repo_id=?", repoID).Get(new(TeamRepo)) + return has +} + +// HasTeamRepo returns true if given repository belongs to team. +func HasTeamRepo(orgID, teamID, repoID int64) bool { + return hasTeamRepo(x, orgID, teamID, repoID) +} + +func addTeamRepo(e Engine, orgID, teamID, repoID int64) error { + _, err := e.InsertOne(&TeamRepo{ + OrgID: orgID, + TeamID: teamID, + RepoID: repoID, + }) + return err +} + +// AddTeamRepo adds new repository relation to team. +func AddTeamRepo(orgID, teamID, repoID int64) error { + return addTeamRepo(x, orgID, teamID, repoID) +} + +func removeTeamRepo(e Engine, teamID, repoID int64) error { + _, err := e.Delete(&TeamRepo{ + TeamID: teamID, + RepoID: repoID, + }) + return err +} + +// RemoveTeamRepo deletes repository relation to team. +func RemoveTeamRepo(teamID, repoID int64) error { + return removeTeamRepo(x, teamID, repoID) +} diff --git a/models/repo.go b/models/repo.go index bfa5925c..7f87bbb2 100644 --- a/models/repo.go +++ b/models/repo.go @@ -514,7 +514,7 @@ func initRepository(e Engine, f string, u *User, repo *Repository, initReadme bo } // CreateRepository creates a repository for given user or organization. -func CreateRepository(u *User, name, desc, lang, license string, private, mirror, initReadme bool) (*Repository, error) { +func CreateRepository(u *User, name, desc, lang, license string, isPrivate, isMirror, initReadme bool) (*Repository, error) { if !IsLegalName(name) { return nil, ErrRepoNameIllegal } @@ -532,7 +532,7 @@ func CreateRepository(u *User, name, desc, lang, license string, private, mirror Name: name, LowerName: strings.ToLower(name), Description: desc, - IsPrivate: private, + IsPrivate: isPrivate, } sess := x.NewSession() @@ -558,34 +558,22 @@ func CreateRepository(u *User, name, desc, lang, license string, private, mirror // Update owner team info and count. t, err := u.getOwnerTeam(sess) if err != nil { - return nil, fmt.Errorf("get owner team: %v", err) - } else if err = t.getMembers(sess); err != nil { - return nil, fmt.Errorf("get team members: %v", err) - } - - for _, u := range t.Members { - if err = watchRepo(sess, u.Id, repo.Id, true); err != nil { - return nil, fmt.Errorf("watch repository: %v", err) - } - } - - t.RepoIds += "$" + com.ToStr(repo.Id) + "|" - t.NumRepos++ - if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { - return nil, err + return nil, fmt.Errorf("getOwnerTeam: %v", err) + } else if err = t.addRepository(sess, repo); err != nil { + return nil, fmt.Errorf("addRepository: %v", err) } } else { if err = watchRepo(sess, u.Id, repo.Id, true); err != nil { - return nil, fmt.Errorf("watch repository 2: %v", err) + return nil, fmt.Errorf("watchRepo: %v", err) } } if err = newRepoAction(sess, u, repo); err != nil { - return nil, fmt.Errorf("new repository action: %v", err) + return nil, fmt.Errorf("newRepoAction: %v", err) } // No need for init mirror. - if !mirror { + if !isMirror { repoPath := RepoPath(u.Name, repo.Name) if err = initRepository(sess, repoPath, u, repo, initReadme, lang, license); err != nil { if err2 := os.RemoveAll(repoPath); err2 != nil { @@ -640,14 +628,14 @@ func RepoPath(userName, repoName string) string { } // TransferOwnership transfers all corresponding setting from old user to new one. -func TransferOwnership(u *User, newOwner string, repo *Repository) error { - newUser, err := GetUserByName(newOwner) +func TransferOwnership(u *User, newOwnerName string, repo *Repository) error { + newOwner, err := GetUserByName(newOwnerName) if err != nil { - return fmt.Errorf("fail to get new owner(%s): %v", newOwner, err) + return fmt.Errorf("get new owner(%s): %v", newOwnerName, err) } // Check if new owner has repository with same name. - has, err := IsRepositoryExist(newUser, repo.Name) + has, err := IsRepositoryExist(newOwner, repo.Name) if err != nil { return err } else if has { @@ -663,8 +651,8 @@ func TransferOwnership(u *User, newOwner string, repo *Repository) error { owner := repo.Owner // Update repository. - repo.OwnerId = newUser.Id - repo.Owner = newUser + repo.OwnerId = newOwner.Id + repo.Owner = newOwner if _, err := sess.Id(repo.Id).Update(repo); err != nil { return err } @@ -675,28 +663,38 @@ func TransferOwnership(u *User, newOwner string, repo *Repository) error { return err } for _, c := range collaborators { - if c.Id == newUser.Id || newUser.IsOrgMember(c.Id) { + if c.Id == newOwner.Id || newOwner.IsOrgMember(c.Id) { if _, err = sess.Delete(&Collaboration{RepoID: repo.Id, UserID: c.Id}); err != nil { return err } } } + if newOwner.IsOrganization() { + // Update owner team info and count. + t, err := newOwner.GetOwnerTeam() + if err != nil { + return err + } else if err = t.addRepository(sess, repo); err != nil { + return err + } + } + // Update user repository number. - if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos + 1 WHERE id = ?", newUser.Id); err != nil { + if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos + 1 WHERE id = ?", newOwner.Id); err != nil { return err } else if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?", owner.Id); err != nil { return err } else if err = repo.recalculateAccesses(sess); err != nil { return err - } else if err = watchRepo(sess, newUser.Id, repo.Id, true); err != nil { + } else if err = watchRepo(sess, newOwner.Id, repo.Id, true); err != nil { return err - } else if err = transferRepoAction(sess, u, newUser, repo); err != nil { + } else if err = transferRepoAction(sess, u, owner, newOwner, repo); err != nil { return err } // Change repository directory name. - if err = os.Rename(RepoPath(owner.Name, repo.Name), RepoPath(newUser.Name, repo.Name)); err != nil { + if err = os.Rename(RepoPath(owner.Name, repo.Name), RepoPath(newOwner.Name, repo.Name)); err != nil { return err } @@ -734,8 +732,8 @@ func UpdateRepository(repo *Repository) error { } // DeleteRepository deletes a repository for a user or organization. -func DeleteRepository(uid, repoId int64, userName string) error { - repo := &Repository{Id: repoId, OwnerId: uid} +func DeleteRepository(uid, repoID int64, userName string) error { + repo := &Repository{Id: repoID, OwnerId: uid} has, err := x.Get(repo) if err != nil { return err @@ -761,70 +759,66 @@ func DeleteRepository(uid, repoId int64, userName string) error { } if org.IsOrganization() { - idStr := "$" + com.ToStr(repoId) + "|" for _, t := range org.Teams { - if !strings.Contains(t.RepoIds, idStr) { + if !t.hasRepository(sess, repoID) { continue - } - t.NumRepos-- - t.RepoIds = strings.Replace(t.RepoIds, idStr, "", 1) - if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { + } else if err = t.removeRepository(sess, repo); err != nil { return err } } } - if _, err = sess.Delete(&Repository{Id: repoId}); err != nil { + if _, err = sess.Delete(&Repository{Id: repoID}); err != nil { return err } else if _, err := sess.Delete(&Access{RepoID: repo.Id}); err != nil { return err } else if _, err := sess.Delete(&Action{RepoId: repo.Id}); err != nil { return err - } else if _, err = sess.Delete(&Watch{RepoId: repoId}); err != nil { + } else if _, err = sess.Delete(&Watch{RepoId: repoID}); err != nil { return err - } else if _, err = sess.Delete(&Mirror{RepoId: repoId}); err != nil { + } else if _, err = sess.Delete(&Mirror{RepoId: repoID}); err != nil { return err - } else if _, err = sess.Delete(&IssueUser{RepoId: repoId}); err != nil { + } else if _, err = sess.Delete(&IssueUser{RepoId: repoID}); err != nil { return err - } else if _, err = sess.Delete(&Milestone{RepoId: repoId}); err != nil { + } else if _, err = sess.Delete(&Milestone{RepoId: repoID}); err != nil { return err - } else if _, err = sess.Delete(&Release{RepoId: repoId}); err != nil { + } else if _, err = sess.Delete(&Release{RepoId: repoID}); err != nil { return err - } else if _, err = sess.Delete(&Collaboration{RepoID: repoId}); err != nil { + } else if _, err = sess.Delete(&Collaboration{RepoID: repoID}); err != nil { return err } // Delete comments. - if err = x.Iterate(&Issue{RepoId: repoId}, func(idx int, bean interface{}) error { - issue := bean.(*Issue) - if _, err = sess.Delete(&Comment{IssueId: issue.Id}); err != nil { + issues := make([]*Issue, 0, 25) + if err = sess.Where("repo_id=?", repoID).Find(&issues); err != nil { + return err + } + for i := range issues { + if _, err = sess.Delete(&Comment{IssueId: issues[i].Id}); err != nil { return err } - return nil - }); err != nil { - return err } - if _, err = sess.Delete(&Issue{RepoId: repoId}); err != nil { + if _, err = sess.Delete(&Issue{RepoId: repoID}); err != nil { return err } if repo.IsFork { - if _, err = sess.Exec("UPDATE `repository` SET num_forks = num_forks - 1 WHERE id = ?", repo.ForkId); err != nil { + if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks-1 WHERE id=?", repo.ForkId); err != nil { return err } } - if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?", uid); err != nil { + if _, err = sess.Exec("UPDATE `user` SET num_repos=num_repos-1 WHERE id=?", uid); err != nil { return err } // Remove repository files. if err = os.RemoveAll(RepoPath(userName, repo.Name)); err != nil { - desc := fmt.Sprintf("Fail to delete repository files(%s/%s): %v", userName, repo.Name, err) + desc := fmt.Sprintf("delete repository files(%s/%s): %v", userName, repo.Name, err) log.Warn(desc) if err = CreateRepositoryNotice(desc); err != nil { - log.Error(4, "Fail to add notice: %v", err) + log.Error(4, "add notice: %v", err) } } @@ -1328,33 +1322,21 @@ func ForkRepository(u *User, oldRepo *Repository, name, desc string) (*Repositor // Update owner team info and count. t, err := u.getOwnerTeam(sess) if err != nil { - return nil, fmt.Errorf("get owner team: %v", err) - } else if err = t.getMembers(sess); err != nil { - return nil, fmt.Errorf("get team members: %v", err) - } - - for _, u := range t.Members { - if err = watchRepo(sess, u.Id, repo.Id, true); err != nil { - return nil, fmt.Errorf("watch repository: %v", err) - } - } - - t.RepoIds += "$" + com.ToStr(repo.Id) + "|" - t.NumRepos++ - if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { - return nil, err + return nil, fmt.Errorf("getOwnerTeam: %v", err) + } else if err = t.addRepository(sess, repo); err != nil { + return nil, fmt.Errorf("addRepository: %v", err) } } else { if err = watchRepo(sess, u.Id, repo.Id, true); err != nil { - return nil, fmt.Errorf("watch repository 2: %v", err) + return nil, fmt.Errorf("watchRepo: %v", err) } } if err = newRepoAction(sess, u, repo); err != nil { - return nil, fmt.Errorf("new repository action: %v", err) + return nil, fmt.Errorf("newRepoAction: %v", err) } - if _, err = sess.Exec("UPDATE `repository` SET num_forks = num_forks + 1 WHERE id = ?", oldRepo.Id); err != nil { + if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks+1 WHERE id=?", oldRepo.Id); err != nil { return nil, err } diff --git a/models/user.go b/models/user.go index 387ab655..ea5041bd 100644 --- a/models/user.go +++ b/models/user.go @@ -231,7 +231,7 @@ func (u *User) GetOrganizations() error { u.Orgs = make([]*User, len(ous)) for i, ou := range ous { - u.Orgs[i], err = GetUserById(ou.OrgId) + u.Orgs[i], err = GetUserById(ou.OrgID) if err != nil { return err } @@ -860,7 +860,7 @@ func UpdateMentions(userNames []string, issueId int64) error { } for _, orgUser := range orgUsers { - tempIds = append(tempIds, orgUser.Id) + tempIds = append(tempIds, orgUser.ID) } ids = append(ids, tempIds...) diff --git a/routers/org/teams.go b/routers/org/teams.go index 2fbb1480..69f2734c 100644 --- a/routers/org/teams.go +++ b/routers/org/teams.go @@ -181,7 +181,7 @@ func NewTeamPost(ctx *middleware.Context, form auth.CreateTeamForm) { org := ctx.Org.Organization t := &models.Team{ - OrgId: org.Id, + OrgID: org.Id, Name: form.TeamName, Description: form.Description, Authorize: auth, diff --git a/routers/repo/setting.go b/routers/repo/setting.go index 0f8acfa5..e2b89683 100644 --- a/routers/repo/setting.go +++ b/routers/repo/setting.go @@ -8,7 +8,6 @@ import ( "encoding/json" "errors" "fmt" - "path" "strings" "time" diff --git a/templates/.VERSION b/templates/.VERSION index 056f3141..4758bb67 100644 --- a/templates/.VERSION +++ b/templates/.VERSION @@ -1 +1 @@ -0.5.14.0222 Beta +0.5.15.0223 Beta \ No newline at end of file -- cgit v1.2.3