From 9135b5eccb21dcc1d00c12e94df30f605f63846e Mon Sep 17 00:00:00 2001 From: Sonic853 Date: Thu, 26 Oct 2023 18:21:17 +0800 Subject: [PATCH 01/11] Members page add invite member --- options/locale/locale_en-US.ini | 3 +++ routers/web/org/members.go | 17 ++++++++++++++++- routers/web/web.go | 1 + templates/org/member/invite.tmpl | 24 ++++++++++++++++++++++++ templates/org/member/members.tmpl | 2 +- 5 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 templates/org/member/invite.tmpl diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index d9d0dd79684fa..1757f91be6c2f 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2629,6 +2629,9 @@ members.remove = Remove members.remove.detail = Remove %[1]s from %[2]s? members.leave = Leave members.leave.detail = Leave %s? +members.invite = Invite +members.to = To +members.team = Team members.invite_desc = Add a new member to %s: members.invite_now = Invite Now diff --git a/routers/web/org/members.go b/routers/web/org/members.go index 15a615c706fe6..d8c9690aecdfc 100644 --- a/routers/web/org/members.go +++ b/routers/web/org/members.go @@ -18,7 +18,8 @@ import ( const ( // tplMembers template for organization members page - tplMembers base.TplName = "org/member/members" + tplMembers base.TplName = "org/member/members" + tplMembersInvite base.TplName = "org/member/invite" ) // Members render organization users page @@ -76,6 +77,20 @@ func Members(ctx *context.Context) { ctx.HTML(http.StatusOK, tplMembers) } +// MembersInvite render organization members invite page +func MembersInvite(ctx *context.Context) { + org := ctx.Org.Organization + ctx.Data["Title"] = org.FullName + ctx.Data["PageIsOrgMembers"] = true + ctx.Data["Teams"] = ctx.Org.Teams + ctx.Data["IsEmailInviteEnabled"] = setting.MailService != nil + if err := shared_user.LoadHeaderCount(ctx); err != nil { + ctx.ServerError("LoadHeaderCount", err) + return + } + ctx.HTML(http.StatusOK, tplMembersInvite) +} + // MembersAction response for operation to a member of organization func MembersAction(ctx *context.Context) { uid := ctx.FormInt64("uid") diff --git a/routers/web/web.go b/routers/web/web.go index 6449f7716cf75..e93390b6b7136 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -796,6 +796,7 @@ func registerRoutes(m *web.Route) { m.Group("/org", func() { m.Group("/{org}", func() { m.Get("/members", org.Members) + m.Get("/members/invite", org.MembersInvite) }, context.OrgAssignment()) }, ignSignIn) diff --git a/templates/org/member/invite.tmpl b/templates/org/member/invite.tmpl new file mode 100644 index 0000000000000..448d789d7615b --- /dev/null +++ b/templates/org/member/invite.tmpl @@ -0,0 +1,24 @@ +{{template "base/head" .}} +
+ {{template "org/header" .}} +
+ {{template "base/alert" .}} + +
+ +
{{ctx.Locale.Tr "org.members.invite"}}
+ +
{{ctx.Locale.Tr "org.members.to"}}
+ +
{{ctx.Locale.Tr "org.members.team"}}
+ +
+
+
+{{template "base/footer" .}} \ No newline at end of file diff --git a/templates/org/member/members.tmpl b/templates/org/member/members.tmpl index e4ddb69805b8d..005cb20032360 100644 --- a/templates/org/member/members.tmpl +++ b/templates/org/member/members.tmpl @@ -1,5 +1,5 @@ {{template "base/head" .}} -
+
{{template "org/header" .}}
{{template "base/alert" .}} From 988dcf715b626870290d268566f83ce22d1ad4fa Mon Sep 17 00:00:00 2001 From: Sonic853 Date: Thu, 26 Oct 2023 20:25:03 +0800 Subject: [PATCH 02/11] Add Invite Member button --- options/locale/locale_en-US.ini | 1 + templates/org/member/members.tmpl | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 1757f91be6c2f..81732f113cfd3 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -2630,6 +2630,7 @@ members.remove.detail = Remove %[1]s from %[2]s? members.leave = Leave members.leave.detail = Leave %s? members.invite = Invite +members.invite_member = Invite Member members.to = To members.team = Team members.invite_desc = Add a new member to %s: diff --git a/templates/org/member/members.tmpl b/templates/org/member/members.tmpl index 005cb20032360..0e8621ceec412 100644 --- a/templates/org/member/members.tmpl +++ b/templates/org/member/members.tmpl @@ -3,6 +3,12 @@ {{template "org/header" .}}
{{template "base/alert" .}} + {{if .IsOrganizationOwner}} + +
+ {{end}}
{{range .Members}} From cf3461024f29eafd7614a3dc1dce1e35cc0aa7bd Mon Sep 17 00:00:00 2001 From: Sonic853 Date: Thu, 26 Oct 2023 20:26:03 +0800 Subject: [PATCH 03/11] Change invite member page --- templates/org/member/invite.tmpl | 32 +++++++++++++++++-------------- web_src/css/base.css | 18 +++++++++++++++++ web_src/js/features/org-member.js | 31 ++++++++++++++++++++++++++++++ web_src/js/index.js | 3 +++ 4 files changed, 70 insertions(+), 14 deletions(-) create mode 100644 web_src/js/features/org-member.js diff --git a/templates/org/member/invite.tmpl b/templates/org/member/invite.tmpl index 448d789d7615b..c10120718b118 100644 --- a/templates/org/member/invite.tmpl +++ b/templates/org/member/invite.tmpl @@ -4,20 +4,24 @@
{{template "base/alert" .}} -
- -
{{ctx.Locale.Tr "org.members.invite"}}
- -
{{ctx.Locale.Tr "org.members.to"}}
- -
{{ctx.Locale.Tr "org.members.team"}}
- +
+

{{ctx.Locale.Tr "org.members.invite_member"}}

+
+ {{.CsrfTokenHtml}} + +
{{ctx.Locale.Tr "org.members.invite"}}
+ +
{{ctx.Locale.Tr "org.members.to"}}
+ +
{{ctx.Locale.Tr "org.members.team"}}
+ +
diff --git a/web_src/css/base.css b/web_src/css/base.css index ae8eb057090e2..e8fd3225ab46d 100644 --- a/web_src/css/base.css +++ b/web_src/css/base.css @@ -193,6 +193,22 @@ a.label, text-decoration: none !important; } +.ui.search > .prompt { + color: var(--color-text); + background: var(--color-box-body); + border-color: var(--color-secondary); +} + +.ui.search .prompt { + border-radius: var(--border-radius); +} + +.ui.search > .prompt:focus { + border-color: var(--color-primary); + background: var(--color-box-body); + color: var(--color-text); +} + .ui.search > .results { background: var(--color-body); border-color: var(--color-secondary); @@ -257,6 +273,8 @@ ol.ui.list li, .ui.input.focus > input, .ui.input > input:focus { border-color: var(--color-primary); + background: var(--color-box-body); + color: var(--color-text); } .ui.action.input .ui.ui.button { diff --git a/web_src/js/features/org-member.js b/web_src/js/features/org-member.js new file mode 100644 index 0000000000000..5ccd86732f526 --- /dev/null +++ b/web_src/js/features/org-member.js @@ -0,0 +1,31 @@ +export function initOrgMemberInvite() { + if (document.querySelector('.page-content.organization.invitemember') === null) { + return; + } + + /** + * @type {HTMLFormElement | null} + */ + const memberInvite = document.querySelector('form.member-invite'); + if (memberInvite === null) { + return; + } + + const orgLink = memberInvite.getAttribute('data-org-link'); + if (orgLink === null) { + return; + } + + /** + * @type {HTMLSelectElement | null} + */ + const teamSelect = memberInvite.querySelector('select[name=team]'); + if (teamSelect === null) { + return; + } + + memberInvite.action = `${orgLink}/teams/${teamSelect.value}/action/add`; + teamSelect.addEventListener('change', () => { + memberInvite.action = `${orgLink}/teams/${teamSelect.value}/action/add`; + }); +} diff --git a/web_src/js/index.js b/web_src/js/index.js index 4713618506b0c..70473ccc113e2 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -64,6 +64,7 @@ import { initRepoSettingSearchTeamBox, } from './features/repo-settings.js'; import {initRepoDiffView} from './features/repo-diff.js'; +import {initOrgMemberInvite} from './features/org-member.js'; import {initOrgTeamSearchRepoBox, initOrgTeamSettings} from './features/org-team.js'; import {initUserAuthWebAuthn, initUserAuthWebAuthnRegister} from './features/user-auth-webauthn.js'; import {initRepoRelease, initRepoReleaseNew} from './features/repo-release.js'; @@ -135,6 +136,8 @@ onDomReady(() => { initNotificationCount(); initNotificationsTable(); + initOrgMemberInvite(); + initOrgTeamSearchRepoBox(); initOrgTeamSettings(); From b3ec624e50b6f28489d92bfd834e03ce960edf61 Mon Sep 17 00:00:00 2001 From: 853 Date: Fri, 27 Oct 2023 03:02:33 +0800 Subject: [PATCH 04/11] Fix errors detected by lint-backend and lint-templates --- templates/org/member/invite.tmpl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/org/member/invite.tmpl b/templates/org/member/invite.tmpl index c10120718b118..cdb7f7908ce74 100644 --- a/templates/org/member/invite.tmpl +++ b/templates/org/member/invite.tmpl @@ -6,7 +6,7 @@

{{ctx.Locale.Tr "org.members.invite_member"}}

-
+ {{.CsrfTokenHtml}}
{{ctx.Locale.Tr "org.members.invite"}}
@@ -25,4 +25,4 @@
-{{template "base/footer" .}} \ No newline at end of file +{{template "base/footer" .}} From e89eec12fcee733a15cad0bbde1a5f98ebb91843 Mon Sep 17 00:00:00 2001 From: 853 Date: Fri, 27 Oct 2023 03:22:09 +0800 Subject: [PATCH 05/11] Replace Spaces with Tabs --- templates/org/member/invite.tmpl | 46 ++++++++++++++++---------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/templates/org/member/invite.tmpl b/templates/org/member/invite.tmpl index cdb7f7908ce74..9d854a9b53cd3 100644 --- a/templates/org/member/invite.tmpl +++ b/templates/org/member/invite.tmpl @@ -1,28 +1,28 @@ {{template "base/head" .}}
- {{template "org/header" .}} -
- {{template "base/alert" .}} + {{template "org/header" .}} +
+ {{template "base/alert" .}} -
-

{{ctx.Locale.Tr "org.members.invite_member"}}

- - {{.CsrfTokenHtml}} - -
{{ctx.Locale.Tr "org.members.invite"}}
- -
{{ctx.Locale.Tr "org.members.to"}}
- -
{{ctx.Locale.Tr "org.members.team"}}
- - -
-
+
+

{{ctx.Locale.Tr "org.members.invite_member"}}

+
+ {{.CsrfTokenHtml}} + +
{{ctx.Locale.Tr "org.members.invite"}}
+ +
{{ctx.Locale.Tr "org.members.to"}}
+ +
{{ctx.Locale.Tr "org.members.team"}}
+ +
+
+
{{template "base/footer" .}} From b41e3d9645b9aadd3fbee26ad30e79af0c55efe3 Mon Sep 17 00:00:00 2001 From: Sonic853 Date: Mon, 30 Oct 2023 11:16:37 +0800 Subject: [PATCH 06/11] Remove js --- web_src/js/features/org-member.js | 31 ------------------------------- web_src/js/index.js | 3 --- 2 files changed, 34 deletions(-) delete mode 100644 web_src/js/features/org-member.js diff --git a/web_src/js/features/org-member.js b/web_src/js/features/org-member.js deleted file mode 100644 index 5ccd86732f526..0000000000000 --- a/web_src/js/features/org-member.js +++ /dev/null @@ -1,31 +0,0 @@ -export function initOrgMemberInvite() { - if (document.querySelector('.page-content.organization.invitemember') === null) { - return; - } - - /** - * @type {HTMLFormElement | null} - */ - const memberInvite = document.querySelector('form.member-invite'); - if (memberInvite === null) { - return; - } - - const orgLink = memberInvite.getAttribute('data-org-link'); - if (orgLink === null) { - return; - } - - /** - * @type {HTMLSelectElement | null} - */ - const teamSelect = memberInvite.querySelector('select[name=team]'); - if (teamSelect === null) { - return; - } - - memberInvite.action = `${orgLink}/teams/${teamSelect.value}/action/add`; - teamSelect.addEventListener('change', () => { - memberInvite.action = `${orgLink}/teams/${teamSelect.value}/action/add`; - }); -} diff --git a/web_src/js/index.js b/web_src/js/index.js index 70473ccc113e2..4713618506b0c 100644 --- a/web_src/js/index.js +++ b/web_src/js/index.js @@ -64,7 +64,6 @@ import { initRepoSettingSearchTeamBox, } from './features/repo-settings.js'; import {initRepoDiffView} from './features/repo-diff.js'; -import {initOrgMemberInvite} from './features/org-member.js'; import {initOrgTeamSearchRepoBox, initOrgTeamSettings} from './features/org-team.js'; import {initUserAuthWebAuthn, initUserAuthWebAuthnRegister} from './features/user-auth-webauthn.js'; import {initRepoRelease, initRepoReleaseNew} from './features/repo-release.js'; @@ -136,8 +135,6 @@ onDomReady(() => { initNotificationCount(); initNotificationsTable(); - initOrgMemberInvite(); - initOrgTeamSearchRepoBox(); initOrgTeamSettings(); From cdfa2ddd54fe7a0d42ef51550ca98a641423225d Mon Sep 17 00:00:00 2001 From: Sonic853 Date: Mon, 30 Oct 2023 11:18:20 +0800 Subject: [PATCH 07/11] add MembersInviteAction --- routers/web/org/members.go | 74 ++++++++++++++++++++++++++++++++ routers/web/web.go | 1 + templates/org/member/invite.tmpl | 30 +++++++------ 3 files changed, 91 insertions(+), 14 deletions(-) diff --git a/routers/web/org/members.go b/routers/web/org/members.go index d8c9690aecdfc..bd8f424c78a12 100644 --- a/routers/web/org/members.go +++ b/routers/web/org/members.go @@ -6,14 +6,19 @@ package org import ( "net/http" + "net/url" + "strings" "code.gitea.io/gitea/models" "code.gitea.io/gitea/models/organization" + user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/routers/utils" shared_user "code.gitea.io/gitea/routers/web/shared/user" + org_service "code.gitea.io/gitea/services/org" ) const ( @@ -91,6 +96,75 @@ func MembersInvite(ctx *context.Context) { ctx.HTML(http.StatusOK, tplMembersInvite) } +// MembersInviteAction response for invite a member to organization +func MembersInviteAction(ctx *context.Context) { + var err error + if !ctx.Org.IsOwner { + ctx.Error(http.StatusNotFound) + return + } + uname := utils.RemoveUsernameParameterSuffix(strings.ToLower(ctx.FormString("uname"))) + var team *organization.Team + team, err = organization.GetTeam(ctx, ctx.Org.Organization.ID, ctx.FormString("team")) + if err != nil { + if organization.IsErrTeamNotExist(err) { + ctx.Flash.Error(ctx.Tr("form.team_not_exist")) + } else { + ctx.ServerError("GetTeam", err) + } + return + } + var u *user_model.User + u, err = user_model.GetUserByName(ctx, uname) + if err != nil { + if user_model.IsErrUserNotExist(err) { + if setting.MailService != nil && user_model.ValidateEmail(uname) == nil { + if err := org_service.CreateTeamInvite(ctx, ctx.Doer, team, uname); err != nil { + if organization.IsErrTeamInviteAlreadyExist(err) { + ctx.Flash.Error(ctx.Tr("form.duplicate_invite_to_team")) + } else if organization.IsErrUserEmailAlreadyAdded(err) { + ctx.Flash.Error(ctx.Tr("org.teams.add_duplicate_users")) + } else { + ctx.ServerError("CreateTeamInvite", err) + return + } + } + } else { + ctx.Flash.Error(ctx.Tr("form.user_not_exist")) + } + ctx.Redirect(ctx.Org.OrgLink + "/teams/" + url.PathEscape(team.LowerName)) + } else { + ctx.ServerError("GetUserByName", err) + } + return + } + + if u.IsOrganization() { + ctx.Flash.Error(ctx.Tr("form.cannot_add_org_to_team")) + ctx.Redirect(ctx.Org.OrgLink + "/teams/" + url.PathEscape(team.LowerName)) + return + } + + if team.IsMember(ctx, u.ID) { + ctx.Flash.Error(ctx.Tr("org.teams.add_duplicate_users")) + } else { + err = models.AddTeamMember(ctx, team, u.ID) + } + if err != nil { + if organization.IsErrLastOrgOwner(err) { + ctx.Flash.Error(ctx.Tr("form.last_org_owner")) + } else { + log.Error("Action(%s): %v", ctx.Params(":action"), err) + ctx.JSON(http.StatusOK, map[string]any{ + "ok": false, + "err": err.Error(), + }) + return + } + } + ctx.Redirect(ctx.Org.OrgLink + "/teams/" + url.PathEscape(team.LowerName)) +} + // MembersAction response for operation to a member of organization func MembersAction(ctx *context.Context) { uid := ctx.FormInt64("uid") diff --git a/routers/web/web.go b/routers/web/web.go index e93390b6b7136..ce7fdabe09135 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -797,6 +797,7 @@ func registerRoutes(m *web.Route) { m.Group("/{org}", func() { m.Get("/members", org.Members) m.Get("/members/invite", org.MembersInvite) + m.Post("/members/invite", org.MembersInviteAction) }, context.OrgAssignment()) }, ignSignIn) diff --git a/templates/org/member/invite.tmpl b/templates/org/member/invite.tmpl index 9d854a9b53cd3..7f8158d3d04d9 100644 --- a/templates/org/member/invite.tmpl +++ b/templates/org/member/invite.tmpl @@ -6,21 +6,23 @@

{{ctx.Locale.Tr "org.members.invite_member"}}

-
- {{.CsrfTokenHtml}} - -
{{ctx.Locale.Tr "org.members.invite"}}
-
From b5933eb41c9de9fb3ecd29895542536004bb10a6 Mon Sep 17 00:00:00 2001 From: Sonic853 Date: Mon, 30 Oct 2023 16:52:03 +0800 Subject: [PATCH 08/11] change data-allow-email-description --- templates/org/member/invite.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/org/member/invite.tmpl b/templates/org/member/invite.tmpl index 7f8158d3d04d9..db965764d84b0 100644 --- a/templates/org/member/invite.tmpl +++ b/templates/org/member/invite.tmpl @@ -11,7 +11,7 @@ {{.CsrfTokenHtml}} -