diff options
Diffstat (limited to '')
39 files changed, 3151 insertions, 0 deletions
diff --git a/templates/admin/actions.tmpl b/templates/admin/actions.tmpl new file mode 100644 index 0000000..597863d --- /dev/null +++ b/templates/admin/actions.tmpl @@ -0,0 +1,10 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin actions")}} + <div class="admin-setting-content"> + {{if eq .PageType "runners"}} + {{template "shared/actions/runner_list" .}} + {{end}} + {{if eq .PageType "variables"}} + {{template "shared/variables/variable_list" .}} + {{end}} + </div> +{{template "admin/layout_footer" .}} diff --git a/templates/admin/applications/list.tmpl b/templates/admin/applications/list.tmpl new file mode 100644 index 0000000..cbb66b1 --- /dev/null +++ b/templates/admin/applications/list.tmpl @@ -0,0 +1,8 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin config")}} + <div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "settings.applications"}} + </h4> + {{template "user/settings/applications_oauth2_list" .}} + </div> +{{template "admin/layout_footer" .}} diff --git a/templates/admin/applications/oauth2_edit.tmpl b/templates/admin/applications/oauth2_edit.tmpl new file mode 100644 index 0000000..668bfe0 --- /dev/null +++ b/templates/admin/applications/oauth2_edit.tmpl @@ -0,0 +1,6 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin config")}} + <div class="admin-setting-content"> + + {{template "user/settings/applications_oauth2_edit_form" .}} + </div> +{{template "admin/layout_footer" .}} diff --git a/templates/admin/auth/edit.tmpl b/templates/admin/auth/edit.tmpl new file mode 100644 index 0000000..a8b2049 --- /dev/null +++ b/templates/admin/auth/edit.tmpl @@ -0,0 +1,464 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin edit authentication")}} + <div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.auths.edit"}} + </h4> + <div class="ui attached segment"> + <form class="ui form" action="{{.Link}}" method="post"> + {{template "base/disable_form_autofill"}} + {{.CsrfTokenHtml}} + <input type="hidden" name="id" value="{{.Source.ID}}"> + <div class="inline field"> + <label>{{ctx.Locale.Tr "admin.auths.auth_type"}}</label> + <input type="hidden" id="auth_type" name="type" value="{{.Source.Type.Int}}"> + <span>{{.Source.TypeName}}</span> + </div> + <div class="required inline field {{if .Err_Name}}error{{end}}"> + <label for="auth_name">{{ctx.Locale.Tr "admin.auths.auth_name"}}</label> + <input id="auth_name" name="name" value="{{.Source.Name}}" autofocus required> + </div> + + <!-- LDAP and DLDAP --> + {{if or .Source.IsLDAP .Source.IsDLDAP}} + {{$cfg:=.Source.Cfg}} + <div class="inline required field {{if .Err_SecurityProtocol}}error{{end}}"> + <label>{{ctx.Locale.Tr "admin.auths.security_protocol"}}</label> + <div class="ui selection security-protocol dropdown"> + <input type="hidden" id="security_protocol" name="security_protocol" value="{{$cfg.SecurityProtocol.Int}}"> + <div class="text">{{$cfg.SecurityProtocolName}}</div> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="menu"> + {{range .SecurityProtocols}} + <div class="item" data-value="{{.Type.Int}}">{{.Name}}</div> + {{end}} + </div> + </div> + </div> + <div class="required field"> + <label for="host">{{ctx.Locale.Tr "admin.auths.host"}}</label> + <input id="host" name="host" value="{{$cfg.Host}}" placeholder="mydomain.com" required> + </div> + <div class="required field"> + <label for="port">{{ctx.Locale.Tr "admin.auths.port"}}</label> + <input id="port" name="port" value="{{$cfg.Port}}" placeholder="636" required> + </div> + <div class="has-tls inline field {{if not .HasTLS}}tw-hidden{{end}}"> + <div class="ui checkbox"> + <label><strong>{{ctx.Locale.Tr "admin.auths.skip_tls_verify"}}</strong></label> + <input name="skip_verify" type="checkbox" {{if .Source.SkipVerify}}checked{{end}}> + </div> + </div> + {{if .Source.IsLDAP}} + <div class="field"> + <label for="bind_dn">{{ctx.Locale.Tr "admin.auths.bind_dn"}}</label> + <input id="bind_dn" name="bind_dn" value="{{$cfg.BindDN}}" placeholder="cn=Search,dc=mydomain,dc=com"> + </div> + <div class="field"> + <label for="bind_password">{{ctx.Locale.Tr "admin.auths.bind_password"}}</label> + <input id="bind_password" name="bind_password" type="password" value="{{$cfg.BindPassword}}"> + </div> + {{end}} + <div class="{{if .Source.IsLDAP}}required{{end}} field"> + <label for="user_base">{{ctx.Locale.Tr "admin.auths.user_base"}}</label> + <input id="user_base" name="user_base" value="{{$cfg.UserBase}}" placeholder="ou=Users,dc=mydomain,dc=com" {{if .Source.IsLDAP}}required{{end}}> + </div> + {{if .Source.IsDLDAP}} + <div class="required field"> + <label for="user_dn">{{ctx.Locale.Tr "admin.auths.user_dn"}}</label> + <input id="user_dn" name="user_dn" value="{{$cfg.UserDN}}" placeholder="uid=%s,ou=Users,dc=mydomain,dc=com" required> + </div> + {{end}} + <div class="required field"> + <label for="filter">{{ctx.Locale.Tr "admin.auths.filter"}}</label> + <input id="filter" name="filter" value="{{$cfg.Filter}}" placeholder="(&(objectClass=posixAccount)(|(uid=%[1]s)(mail=%[1]s)))" required> + </div> + <div class="field"> + <label for="admin_filter">{{ctx.Locale.Tr "admin.auths.admin_filter"}}</label> + <input id="admin_filter" name="admin_filter" value="{{$cfg.AdminFilter}}"> + </div> + <div class="field"> + <label for="restricted_filter">{{ctx.Locale.Tr "admin.auths.restricted_filter"}}</label> + <input id="restricted_filter" name="restricted_filter" value="{{$cfg.RestrictedFilter}}"> + <p class="help">{{ctx.Locale.Tr "admin.auths.restricted_filter_helper"}}</p> + </div> + <div class="field"> + <label for="attribute_username">{{ctx.Locale.Tr "admin.auths.attribute_username"}}</label> + <input id="attribute_username" name="attribute_username" value="{{$cfg.AttributeUsername}}" placeholder="{{ctx.Locale.Tr "admin.auths.attribute_username_placeholder"}}"> + </div> + <div class="field"> + <label for="attribute_name">{{ctx.Locale.Tr "admin.auths.attribute_name"}}</label> + <input id="attribute_name" name="attribute_name" value="{{$cfg.AttributeName}}"> + </div> + <div class="field"> + <label for="attribute_surname">{{ctx.Locale.Tr "admin.auths.attribute_surname"}}</label> + <input id="attribute_surname" name="attribute_surname" value="{{$cfg.AttributeSurname}}"> + </div> + <div class="required field"> + <label for="attribute_mail">{{ctx.Locale.Tr "admin.auths.attribute_mail"}}</label> + <input id="attribute_mail" name="attribute_mail" value="{{$cfg.AttributeMail}}" placeholder="mail" required> + </div> + <div class="field"> + <label for="default_domain_name">{{ctx.Locale.Tr "admin.auths.default_domain_name"}}</label> + <input id="default_domain_name" name="default_domain_name" value="{{$cfg.DefaultDomainName}}" placeholder="localhost.local" > + </div> + <div class="field"> + <label for="attribute_ssh_public_key">{{ctx.Locale.Tr "admin.auths.attribute_ssh_public_key"}}</label> + <input id="attribute_ssh_public_key" name="attribute_ssh_public_key" value="{{$cfg.AttributeSSHPublicKey}}" placeholder="SshPublicKey"> + </div> + <div class="field"> + <label for="attribute_avatar">{{ctx.Locale.Tr "admin.auths.attribute_avatar"}}</label> + <input id="attribute_avatar" name="attribute_avatar" value="{{$cfg.AttributeAvatar}}" placeholder="jpegPhoto"> + </div> + + <!-- ldap group begin --> + <div class="inline field"> + <div class="ui checkbox"> + <label><strong>{{ctx.Locale.Tr "admin.auths.enable_ldap_groups"}}</strong></label> + <input type="checkbox" name="groups_enabled" class="js-ldap-group-toggle" {{if $cfg.GroupsEnabled}}checked{{end}}> + </div> + </div> + <div id="ldap-group-options" class="ui segment secondary {{if not $cfg.GroupsEnabled}}tw-hidden{{end}}"> + <div class="field"> + <label>{{ctx.Locale.Tr "admin.auths.group_search_base"}}</label> + <input name="group_dn" value="{{$cfg.GroupDN}}" placeholder="ou=group,dc=mydomain,dc=com"> + </div> + <div class="field"> + <label>{{ctx.Locale.Tr "admin.auths.group_attribute_list_users"}}</label> + <input name="group_member_uid" value="{{$cfg.GroupMemberUID}}" placeholder="memberUid"> + </div> + <div class="field"> + <label>{{ctx.Locale.Tr "admin.auths.user_attribute_in_group"}}</label> + <input name="user_uid" value="{{$cfg.UserUID}}" placeholder="uid"> + </div> + <div class="field"> + <label>{{ctx.Locale.Tr "admin.auths.verify_group_membership"}}</label> + <input name="group_filter" value="{{$cfg.GroupFilter}}" placeholder="(|(cn=gitea_users)(cn=admins))"> + </div> + <div class="field"> + <label>{{ctx.Locale.Tr "admin.auths.map_group_to_team"}}</label> + <textarea name="group_team_map" rows="5" placeholder='{"cn=my-group,cn=groups,dc=example,dc=org": {"MyForgejoOrganization": ["MyForgejoTeam1", "MyForgejoTeam2"]}}'>{{$cfg.GroupTeamMap}}</textarea> + </div> + <div class="ui checkbox"> + <label>{{ctx.Locale.Tr "admin.auths.map_group_to_team_removal"}}</label> + <input name="group_team_map_removal" type="checkbox" {{if $cfg.GroupTeamMapRemoval}}checked{{end}}> + </div> + </div> + <!-- ldap group end --> + + {{if .Source.IsLDAP}} + <div class="inline field"> + <div class="ui checkbox"> + <label for="use_paged_search"><strong>{{ctx.Locale.Tr "admin.auths.use_paged_search"}}</strong></label> + <input id="use_paged_search" name="use_paged_search" type="checkbox" {{if $cfg.UsePagedSearch}}checked{{end}}> + </div> + </div> + <div class="field required search-page-size{{if not $cfg.UsePagedSearch}} tw-hidden{{end}}"> + <label for="search_page_size">{{ctx.Locale.Tr "admin.auths.search_page_size"}}</label> + <input id="search_page_size" name="search_page_size" value="{{if $cfg.UsePagedSearch}}{{$cfg.SearchPageSize}}{{end}}"> + </div> + <div class="inline field"> + <div class="ui checkbox"> + <label><strong>{{ctx.Locale.Tr "admin.auths.attributes_in_bind"}}</strong></label> + <input name="attributes_in_bind" type="checkbox" {{if $cfg.AttributesInBind}}checked{{end}}> + </div> + </div> + {{end}} + <div class="optional field"> + <div class="ui checkbox"> + <label for="skip_local_two_fa"><strong>{{ctx.Locale.Tr "admin.auths.skip_local_two_fa"}}</strong></label> + <input id="skip_local_two_fa" name="skip_local_two_fa" type="checkbox" {{if $cfg.SkipLocalTwoFA}}checked{{end}}> + <p class="help">{{ctx.Locale.Tr "admin.auths.skip_local_two_fa_helper"}}</p> + </div> + </div> + <div class="inline field"> + <div class="ui checkbox"> + <label for="allow_deactivate_all"><strong>{{ctx.Locale.Tr "admin.auths.allow_deactivate_all"}}</strong></label> + <input id="allow_deactivate_all" name="allow_deactivate_all" type="checkbox" {{if $cfg.AllowDeactivateAll}}checked{{end}}> + </div> + </div> + {{end}} + + <!-- SMTP --> + {{if .Source.IsSMTP}} + {{$cfg:=.Source.Cfg}} + <div class="inline required field"> + <label>{{ctx.Locale.Tr "admin.auths.smtp_auth"}}</label> + <div class="ui selection type dropdown"> + <input type="hidden" id="smtp_auth" name="smtp_auth" value="{{$cfg.Auth}}" required> + <div class="text">{{$cfg.Auth}}</div> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="menu"> + {{range .SMTPAuths}} + <div class="item" data-value="{{.}}">{{.}}</div> + {{end}} + </div> + </div> + </div> + <div class="required field"> + <label for="smtp_host">{{ctx.Locale.Tr "admin.auths.smtphost"}}</label> + <input id="smtp_host" name="smtp_host" value="{{$cfg.Host}}" required> + </div> + <div class="required field"> + <label for="smtp_port">{{ctx.Locale.Tr "admin.auths.smtpport"}}</label> + <input id="smtp_port" name="smtp_port" value="{{$cfg.Port}}" required> + </div> + <div class="field"> + <div class="ui checkbox"> + <label for="force_smtps"><strong>{{ctx.Locale.Tr "admin.auths.force_smtps"}}</strong></label> + <input id="force_smtps" name="force_smtps" type="checkbox" {{if $cfg.ForceSMTPS}}checked{{end}}> + </div> + <p class="help">{{ctx.Locale.Tr "admin.auths.force_smtps_helper"}}</p> + </div> + <div class="has-tls inline field {{if not .HasTLS}}tw-hidden{{end}}"> + <div class="ui checkbox"> + <label><strong>{{ctx.Locale.Tr "admin.auths.skip_tls_verify"}}</strong></label> + <input name="skip_verify" type="checkbox" {{if $cfg.SkipVerify}}checked{{end}}> + </div> + </div> + <div class="field"> + <label for="helo_hostname">{{ctx.Locale.Tr "admin.auths.helo_hostname"}}</label> + <input id="helo_hostname" name="helo_hostname" value="{{$cfg.HeloHostname}}"> + <p class="help">{{ctx.Locale.Tr "admin.auths.helo_hostname_helper"}}</p> + </div> + <div class="inline field"> + <div class="ui checkbox"> + <label for="disable_helo"><strong>{{ctx.Locale.Tr "admin.auths.disable_helo"}}</strong></label> + <input id="disable_helo" name="disable_helo" type="checkbox" {{if $cfg.DisableHelo}}checked{{end}}> + </div> + </div> + <div class="field"> + <label for="allowed_domains">{{ctx.Locale.Tr "admin.auths.allowed_domains"}}</label> + <input id="allowed_domains" name="allowed_domains" value="{{$cfg.AllowedDomains}}"> + <p class="help">{{ctx.Locale.Tr "admin.auths.allowed_domains_helper"}}</p> + </div> + <div class="optional field"> + <div class="ui checkbox"> + <label for="skip_local_two_fa"><strong>{{ctx.Locale.Tr "admin.auths.skip_local_two_fa"}}</strong></label> + <input id="skip_local_two_fa" name="skip_local_two_fa" type="checkbox" {{if $cfg.SkipLocalTwoFA}}checked{{end}}> + <p class="help">{{ctx.Locale.Tr "admin.auths.skip_local_two_fa_helper"}}</p> + </div> + </div> + {{end}} + + <!-- PAM --> + {{if .Source.IsPAM}} + {{$cfg:=.Source.Cfg}} + <div class="required field"> + <label for="pam_service_name">{{ctx.Locale.Tr "admin.auths.pam_service_name"}}</label> + <input id="pam_service_name" name="pam_service_name" value="{{$cfg.ServiceName}}" required> + </div> + <div class="field"> + <label for="pam_email_domain">{{ctx.Locale.Tr "admin.auths.pam_email_domain"}}</label> + <input id="pam_email_domain" name="pam_email_domain" value="{{$cfg.EmailDomain}}"> + </div> + <div class="optional field"> + <div class="ui checkbox"> + <label for="skip_local_two_fa"><strong>{{ctx.Locale.Tr "admin.auths.skip_local_two_fa"}}</strong></label> + <input id="skip_local_two_fa" name="skip_local_two_fa" type="checkbox" {{if $cfg.SkipLocalTwoFA}}checked{{end}}> + <p class="help">{{ctx.Locale.Tr "admin.auths.skip_local_two_fa_helper"}}</p> + </div> + </div> + {{end}} + + <!-- OAuth2 --> + {{if .Source.IsOAuth2}} + {{$cfg:=.Source.Cfg}} + <div class="inline required field"> + <label>{{ctx.Locale.Tr "admin.auths.oauth2_provider"}}</label> + <div class="ui selection type dropdown"> + <input type="hidden" id="oauth2_provider" name="oauth2_provider" value="{{$cfg.Provider}}" required> + <div class="text">{{.CurrentOAuth2Provider.DisplayName}}</div> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="menu"> + {{range .OAuth2Providers}} + <div class="item" data-value="{{.Name}}">{{.DisplayName}}</div> + {{end}} + </div> + </div> + </div> + <div class="required field"> + <label for="oauth2_key">{{ctx.Locale.Tr "admin.auths.oauth2_clientID"}}</label> + <input id="oauth2_key" name="oauth2_key" value="{{$cfg.ClientID}}" required> + </div> + <div class="required field"> + <label for="oauth2_secret">{{ctx.Locale.Tr "admin.auths.oauth2_clientSecret"}}</label> + <input id="oauth2_secret" name="oauth2_secret" value="{{$cfg.ClientSecret}}" required> + </div> + <div class="optional field"> + <label for="oauth2_icon_url">{{ctx.Locale.Tr "admin.auths.oauth2_icon_url"}}</label> + <input id="oauth2_icon_url" name="oauth2_icon_url" value="{{$cfg.IconURL}}"> + </div> + <div class="open_id_connect_auto_discovery_url required field"> + <label for="open_id_connect_auto_discovery_url">{{ctx.Locale.Tr "admin.auths.openIdConnectAutoDiscoveryURL"}}</label> + <input id="open_id_connect_auto_discovery_url" name="open_id_connect_auto_discovery_url" value="{{$cfg.OpenIDConnectAutoDiscoveryURL}}"> + </div> + <div class="optional field"> + <div class="ui checkbox"> + <label for="skip_local_two_fa"><strong>{{ctx.Locale.Tr "admin.auths.skip_local_two_fa"}}</strong></label> + <input id="skip_local_two_fa" name="skip_local_two_fa" type="checkbox" {{if $cfg.SkipLocalTwoFA}}checked{{end}}> + <p class="help">{{ctx.Locale.Tr "admin.auths.skip_local_two_fa_helper"}}</p> + </div> + </div> + <div class="oauth2_use_custom_url inline field"> + <div class="ui checkbox"> + <label><strong>{{ctx.Locale.Tr "admin.auths.oauth2_use_custom_url"}}</strong></label> + <input id="oauth2_use_custom_url" name="oauth2_use_custom_url" type="checkbox" {{if $cfg.CustomURLMapping}}checked{{end}}> + </div> + </div> + <div class="oauth2_use_custom_url_field oauth2_auth_url required field"> + <label for="oauth2_auth_url">{{ctx.Locale.Tr "admin.auths.oauth2_authURL"}}</label> + <input id="oauth2_auth_url" name="oauth2_auth_url" value="{{if $cfg.CustomURLMapping}}{{$cfg.CustomURLMapping.AuthURL}}{{end}}"> + </div> + <div class="oauth2_use_custom_url_field oauth2_token_url required field"> + <label for="oauth2_token_url">{{ctx.Locale.Tr "admin.auths.oauth2_tokenURL"}}</label> + <input id="oauth2_token_url" name="oauth2_token_url" value="{{if $cfg.CustomURLMapping}}{{$cfg.CustomURLMapping.TokenURL}}{{end}}"> + </div> + <div class="oauth2_use_custom_url_field oauth2_profile_url required field"> + <label for="oauth2_profile_url">{{ctx.Locale.Tr "admin.auths.oauth2_profileURL"}}</label> + <input id="oauth2_profile_url" name="oauth2_profile_url" value="{{if $cfg.CustomURLMapping}}{{$cfg.CustomURLMapping.ProfileURL}}{{end}}"> + </div> + <div class="oauth2_use_custom_url_field oauth2_email_url required field"> + <label for="oauth2_email_url">{{ctx.Locale.Tr "admin.auths.oauth2_emailURL"}}</label> + <input id="oauth2_email_url" name="oauth2_email_url" value="{{if $cfg.CustomURLMapping}}{{$cfg.CustomURLMapping.EmailURL}}{{end}}"> + </div> + <div class="oauth2_use_custom_url_field oauth2_tenant required field"> + <label for="oauth2_tenant">{{ctx.Locale.Tr "admin.auths.oauth2_tenant"}}</label> + <input id="oauth2_tenant" name="oauth2_tenant" value="{{if $cfg.CustomURLMapping}}{{$cfg.CustomURLMapping.Tenant}}{{end}}"> + </div> + + {{range .OAuth2Providers}}{{if .CustomURLSettings}} + <input id="{{.Name}}_customURLSettings" type="hidden" data-required="{{.CustomURLSettings.Required}}" data-available="true"> + <input id="{{.Name}}_token_url" value="{{.CustomURLSettings.TokenURL.Value}}" data-available="{{.CustomURLSettings.TokenURL.Available}}" data-required="{{.CustomURLSettings.TokenURL.Required}}" type="hidden"> + <input id="{{.Name}}_auth_url" value="{{.CustomURLSettings.AuthURL.Value}}" data-available="{{.CustomURLSettings.AuthURL.Available}}" data-required="{{.CustomURLSettings.AuthURL.Required}}" type="hidden"> + <input id="{{.Name}}_profile_url" value="{{.CustomURLSettings.ProfileURL.Value}}" data-available="{{.CustomURLSettings.ProfileURL.Available}}" data-required="{{.CustomURLSettings.ProfileURL.Required}}" type="hidden"> + <input id="{{.Name}}_email_url" value="{{.CustomURLSettings.EmailURL.Value}}" data-available="{{.CustomURLSettings.EmailURL.Available}}" data-required="{{.CustomURLSettings.EmailURL.Required}}" type="hidden"> + <input id="{{.Name}}_tenant" value="{{.CustomURLSettings.Tenant.Value}}" data-available="{{.CustomURLSettings.Tenant.Available}}" data-required="{{.CustomURLSettings.Tenant.Required}}" type="hidden"> + {{end}}{{end}} + + <div class="field"> + <label for="oauth2_scopes">{{ctx.Locale.Tr "admin.auths.oauth2_scopes"}}</label> + <input id="oauth2_scopes" name="oauth2_scopes" value="{{if $cfg.Scopes}}{{StringUtils.Join $cfg.Scopes ","}}{{end}}"> + </div> + <div class="field"> + <label for="oauth2_required_claim_name">{{ctx.Locale.Tr "admin.auths.oauth2_required_claim_name"}}</label> + <input id="oauth2_required_claim_name" name="oauth2_required_claim_name" value="{{$cfg.RequiredClaimName}}"> + <p class="help">{{ctx.Locale.Tr "admin.auths.oauth2_required_claim_name_helper"}}</p> + </div> + <div class="field"> + <label for="oauth2_required_claim_value">{{ctx.Locale.Tr "admin.auths.oauth2_required_claim_value"}}</label> + <input id="oauth2_required_claim_value" name="oauth2_required_claim_value" value="{{$cfg.RequiredClaimValue}}"> + <p class="help">{{ctx.Locale.Tr "admin.auths.oauth2_required_claim_value_helper"}}</p> + </div> + <div class="field"> + <label for="oauth2_group_claim_name">{{ctx.Locale.Tr "admin.auths.oauth2_group_claim_name"}}</label> + <input id="oauth2_group_claim_name" name="oauth2_group_claim_name" value="{{$cfg.GroupClaimName}}"> + </div> + <div class="field"> + <label for="oauth2_admin_group">{{ctx.Locale.Tr "admin.auths.oauth2_admin_group"}}</label> + <input id="oauth2_admin_group" name="oauth2_admin_group" value="{{$cfg.AdminGroup}}"> + </div> + <div class="field"> + <label for="oauth2_restricted_group">{{ctx.Locale.Tr "admin.auths.oauth2_restricted_group"}}</label> + <input id="oauth2_restricted_group" name="oauth2_restricted_group" value="{{$cfg.RestrictedGroup}}"> + </div> + <div class="field"> + <label>{{ctx.Locale.Tr "admin.auths.oauth2_map_group_to_team"}}</label> + <textarea name="oauth2_group_team_map" rows="5" placeholder='{"Developer": {"MyForgejoOrganization": ["MyForgejoTeam1", "MyForgejoTeam2"]}}'>{{$cfg.GroupTeamMap}}</textarea> + </div> + <div class="ui checkbox"> + <label>{{ctx.Locale.Tr "admin.auths.oauth2_map_group_to_team_removal"}}</label> + <input name="oauth2_group_team_map_removal" type="checkbox" {{if $cfg.GroupTeamMapRemoval}}checked{{end}}> + </div> + {{end}} + + <!-- SSPI --> + {{if .Source.IsSSPI}} + {{$cfg:=.Source.Cfg}} + <div class="field"> + <div class="ui checkbox"> + <label for="sspi_auto_create_users"><strong>{{ctx.Locale.Tr "admin.auths.sspi_auto_create_users"}}</strong></label> + <input id="sspi_auto_create_users" name="sspi_auto_create_users" class="sspi-auto-create-users" type="checkbox" {{if $cfg.AutoCreateUsers}}checked{{end}}> + <p class="help">{{ctx.Locale.Tr "admin.auths.sspi_auto_create_users_helper"}}</p> + </div> + </div> + <div class="field"> + <div class="ui checkbox"> + <label for="sspi_auto_activate_users"><strong>{{ctx.Locale.Tr "admin.auths.sspi_auto_activate_users"}}</strong></label> + <input id="sspi_auto_activate_users" name="sspi_auto_activate_users" class="sspi-auto-activate-users" type="checkbox" {{if $cfg.AutoActivateUsers}}checked{{end}}> + <p class="help">{{ctx.Locale.Tr "admin.auths.sspi_auto_activate_users_helper"}}</p> + </div> + </div> + <div class="field"> + <div class="ui checkbox"> + <label for="sspi_strip_domain_names"><strong>{{ctx.Locale.Tr "admin.auths.sspi_strip_domain_names"}}</strong></label> + <input id="sspi_strip_domain_names" name="sspi_strip_domain_names" class="sspi-strip-domain-names" type="checkbox" {{if $cfg.StripDomainNames}}checked{{end}}> + <p class="help">{{ctx.Locale.Tr "admin.auths.sspi_strip_domain_names_helper"}}</p> + </div> + </div> + <div class="required field"> + <label for="sspi_separator_replacement">{{ctx.Locale.Tr "admin.auths.sspi_separator_replacement"}}</label> + <input id="sspi_separator_replacement" name="sspi_separator_replacement" value="{{$cfg.SeparatorReplacement}}" required> + <p class="help">{{ctx.Locale.Tr "admin.auths.sspi_separator_replacement_helper"}}</p> + </div> + <div class="field"> + <label for="sspi_default_language">{{ctx.Locale.Tr "admin.auths.sspi_default_language"}}</label> + <div class="ui language selection dropdown" id="sspi_default_language"> + <input name="sspi_default_language" type="hidden" value="{{$cfg.DefaultLanguage}}"> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="text">{{range .AllLangs}}{{if eq $cfg.DefaultLanguage .Lang}}{{.Name}}{{end}}{{end}}</div> + <div class="menu"> + <div class="item{{if not $.SSPIDefaultLanguage}} active selected{{end}}" data-value="">-</div> + {{range .AllLangs}} + <div class="item{{if eq $cfg.DefaultLanguage .Lang}} active selected{{end}}" data-value="{{.Lang}}">{{.Name}}</div> + {{end}} + </div> + </div> + <p class="help">{{ctx.Locale.Tr "admin.auths.sspi_default_language_helper"}}</p> + </div> + {{end}} + {{if (or .Source.IsLDAP .Source.IsOAuth2)}} + <div class="inline field"> + <div class="ui checkbox"> + <label><strong>{{ctx.Locale.Tr "admin.auths.syncenabled"}}</strong></label> + <input name="is_sync_enabled" type="checkbox" {{if .Source.IsSyncEnabled}}checked{{end}}> + </div> + </div> + {{end}} + <div class="inline field"> + <div class="ui checkbox"> + <label><strong>{{ctx.Locale.Tr "admin.auths.activated"}}</strong></label> + <input name="is_active" type="checkbox" {{if .Source.IsActive}}checked{{end}}> + </div> + </div> + + <div class="field"> + <button class="ui primary button">{{ctx.Locale.Tr "admin.auths.update"}}</button> + <button class="ui red button delete-button" data-url="{{$.Link}}/delete" data-id="{{.Source.ID}}">{{ctx.Locale.Tr "admin.auths.delete"}}</button> + </div> + </form> + </div> + + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.auths.tips"}} + </h4> + <div class="ui attached segment"> + <h5>{{ctx.Locale.Tr "admin.auths.tips.gmail_settings"}}</h5> + <p>Host: smtp.gmail.com, Port: 587, Enable TLS Encryption: true</p> + + <h5 class="oauth2">{{ctx.Locale.Tr "admin.auths.tips.oauth2.general"}}:</h5> + <p class="oauth2">{{ctx.Locale.Tr "admin.auths.tips.oauth2.general.tip"}} <b id="oauth2-callback-url"></b></p> + </div> + </div> + +<div class="ui g-modal-confirm delete modal"> + <div class="header"> + {{svg "octicon-trash"}} + {{ctx.Locale.Tr "admin.auths.delete_auth_title"}} + </div> + <div class="content"> + <p>{{ctx.Locale.Tr "admin.auths.delete_auth_desc"}}</p> + </div> + {{template "base/modal_actions_confirm" .}} +</div> + +{{template "admin/layout_footer" .}} diff --git a/templates/admin/auth/list.tmpl b/templates/admin/auth/list.tmpl new file mode 100644 index 0000000..6483ec8 --- /dev/null +++ b/templates/admin/auth/list.tmpl @@ -0,0 +1,38 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin authentication")}} + <div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.auths.auth_manage_panel"}} ({{ctx.Locale.Tr "admin.total" .Total}}) + <div class="ui right"> + <a class="ui primary tiny button" href="{{AppSubUrl}}/admin/auths/new">{{ctx.Locale.Tr "admin.auths.new"}}</a> + </div> + </h4> + <div class="ui attached table segment"> + <table class="ui very basic striped table unstackable"> + <thead> + <tr> + <th>ID</th> + <th>{{ctx.Locale.Tr "admin.auths.name"}}</th> + <th>{{ctx.Locale.Tr "admin.auths.type"}}</th> + <th>{{ctx.Locale.Tr "admin.auths.enabled"}}</th> + <th>{{ctx.Locale.Tr "admin.auths.updated"}}</th> + <th>{{ctx.Locale.Tr "admin.users.created"}}</th> + <th>{{ctx.Locale.Tr "admin.users.edit"}}</th> + </tr> + </thead> + <tbody> + {{range .Sources}} + <tr> + <td>{{.ID}}</td> + <td><a href="{{AppSubUrl}}/admin/auths/{{.ID}}">{{.Name}}</a></td> + <td>{{.TypeName}}</td> + <td>{{if .IsActive}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td> + <td>{{DateTime "short" .UpdatedUnix}}</td> + <td>{{DateTime "short" .CreatedUnix}}</td> + <td><a href="{{AppSubUrl}}/admin/auths/{{.ID}}">{{svg "octicon-pencil"}}</a></td> + </tr> + {{end}} + </tbody> + </table> + </div> + </div> +{{template "admin/layout_footer" .}} diff --git a/templates/admin/auth/new.tmpl b/templates/admin/auth/new.tmpl new file mode 100644 index 0000000..47fa828 --- /dev/null +++ b/templates/admin/auth/new.tmpl @@ -0,0 +1,122 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin new authentication")}} + <div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.auths.new"}} + </h4> + <div class="ui attached segment"> + <form class="ui form" action="{{.Link}}" method="post"> + {{template "base/disable_form_autofill"}} + {{.CsrfTokenHtml}} + <!-- Types and name --> + <div class="inline required field {{if .Err_Type}}error{{end}}"> + <label>{{ctx.Locale.Tr "admin.auths.auth_type"}}</label> + <div class="ui selection type dropdown"> + <input type="hidden" id="auth_type" name="type" value="{{.type}}"> + <div class="text">{{.CurrentTypeName}}</div> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="menu"> + {{range .AuthSources}} + <div class="item" data-value="{{.Type.Int}}">{{.Name}}</div> + {{end}} + </div> + </div> + </div> + <div class="required inline field {{if .Err_Name}}error{{end}}"> + <label for="auth_name">{{ctx.Locale.Tr "admin.auths.auth_name"}}</label> + <input id="auth_name" name="name" value="{{.name}}" autofocus required> + </div> + + <!-- LDAP and DLDAP --> + {{template "admin/auth/source/ldap" .}} + + <!-- SMTP --> + {{template "admin/auth/source/smtp" .}} + + <!-- PAM --> + <div class="pam required field {{if not (eq .type 4)}}tw-hidden{{end}}"> + <label for="pam_service_name">{{ctx.Locale.Tr "admin.auths.pam_service_name"}}</label> + <input id="pam_service_name" name="pam_service_name" value="{{.pam_service_name}}"> + <label for="pam_email_domain">{{ctx.Locale.Tr "admin.auths.pam_email_domain"}}</label> + <input id="pam_email_domain" name="pam_email_domain" value="{{.pam_email_domain}}"> + </div> + <div class="pam optional field {{if not (eq .type 4)}}tw-hidden{{end}}"> + <div class="ui checkbox"> + <label for="skip_local_two_fa"><strong>{{ctx.Locale.Tr "admin.auths.skip_local_two_fa"}}</strong></label> + <input id="skip_local_two_fa" name="skip_local_two_fa" type="checkbox" {{if .skip_local_two_fa}}checked{{end}}> + <p class="help">{{ctx.Locale.Tr "admin.auths.skip_local_two_fa_helper"}}</p> + </div> + </div> + + <!-- OAuth2 --> + {{template "admin/auth/source/oauth" .}} + + <!-- SSPI --> + {{template "admin/auth/source/sspi" .}} + + <div class="ldap field"> + <div class="ui checkbox"> + <label><strong>{{ctx.Locale.Tr "admin.auths.attributes_in_bind"}}</strong></label> + <input name="attributes_in_bind" type="checkbox" {{if .attributes_in_bind}}checked{{end}}> + </div> + </div> + <div class="oauth2 ldap inline field {{if not (or (eq .type 2) (eq .type 6))}}tw-hidden{{end}}"> + <div class="ui checkbox"> + <label><strong>{{ctx.Locale.Tr "admin.auths.syncenabled"}}</strong></label> + <input name="is_sync_enabled" type="checkbox" {{if .is_sync_enabled}}checked{{end}}> + </div> + </div> + <div class="inline field"> + <div class="ui checkbox"> + <label><strong>{{ctx.Locale.Tr "admin.auths.activated"}}</strong></label> + <input name="is_active" type="checkbox" {{if .is_active}}checked{{end}}> + </div> + </div> + + <div class="field"> + <button class="ui primary button">{{ctx.Locale.Tr "admin.auths.new"}}</button> + </div> + </form> + </div> + + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.auths.tips"}} + </h4> + <div class="ui attached segment"> + <h5>{{ctx.Locale.Tr "admin.auths.tips.gmail_settings"}}</h5> + <p>Host: smtp.gmail.com, Port: 587, Enable TLS Encryption: true</p> + + <h5 class="oauth2">{{ctx.Locale.Tr "admin.auths.tips.oauth2.general"}}:</h5> + <p class="oauth2">{{ctx.Locale.Tr "admin.auths.tips.oauth2.general.tip"}} <b id="oauth2-callback-url"></b></p> + + <h5 class="ui top attached header">{{ctx.Locale.Tr "admin.auths.tip.oauth2_provider"}}</h5> + <div class="ui attached segment"> + <li>Bitbucket</li> + <span>{{ctx.Locale.Tr "admin.auths.tip.bitbucket" "https://bitbucket.org/account/user/{your-username}/oauth-consumers/new"}}</span> + <li>Dropbox</li> + <span>{{ctx.Locale.Tr "admin.auths.tip.dropbox" "https://www.dropbox.com/developers/apps"}}</span> + <li>Facebook</li> + <span>{{ctx.Locale.Tr "admin.auths.tip.facebook" "https://developers.facebook.com/apps"}}</span> + <li>GitHub</li> + <span>{{ctx.Locale.Tr "admin.auths.tip.github" "https://github.com/settings/applications/new"}}</span> + <li>GitLab</li> + <span>{{ctx.Locale.Tr "admin.auths.tip.gitlab_new" "https://gitlab.com/-/profile/applications"}}</span> + <li>Google</li> + <span>{{ctx.Locale.Tr "admin.auths.tip.google_plus" "https://console.developers.google.com/"}}</span> + <li>OpenID Connect</li> + <span>{{ctx.Locale.Tr "admin.auths.tip.openid_connect"}}</span> + <li>Twitter</li> + <span>{{ctx.Locale.Tr "admin.auths.tip.twitter" "https://dev.twitter.com/apps"}}</span> + <li>Discord</li> + <span>{{ctx.Locale.Tr "admin.auths.tip.discord" "https://discordapp.com/developers/applications/me"}}</span> + <li>Gitea</li> + <span>{{ctx.Locale.Tr "admin.auths.tip.gitea" "https://forgejo.org/docs/latest/user/oauth2-provider"}}</span> + <li>Nextcloud</li> + <span>{{ctx.Locale.Tr "admin.auths.tip.nextcloud"}}</span> + <li>Yandex</li> + <span>{{ctx.Locale.Tr "admin.auths.tip.yandex" "https://oauth.yandex.com/client/new"}}</span> + <li>Mastodon</li> + <span>{{ctx.Locale.Tr "admin.auths.tip.mastodon"}}</span> + </div> + </div> + </div> +{{template "admin/layout_footer" .}} diff --git a/templates/admin/auth/source/ldap.tmpl b/templates/admin/auth/source/ldap.tmpl new file mode 100644 index 0000000..6cb6643 --- /dev/null +++ b/templates/admin/auth/source/ldap.tmpl @@ -0,0 +1,145 @@ +<div class="ldap dldap field {{if not (or (eq .type 2) (eq .type 5))}}tw-hidden{{end}}"> + <div class="inline required field {{if .Err_SecurityProtocol}}error{{end}}"> + <label>{{ctx.Locale.Tr "admin.auths.security_protocol"}}</label> + <div class="ui selection security-protocol dropdown"> + <input type="hidden" id="security_protocol" name="security_protocol" value="{{.security_protocol}}"> + <div class="text">{{.CurrentSecurityProtocol}}</div> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="menu"> + {{range .SecurityProtocols}} + <div class="item" data-value="{{.Type.Int}}">{{.Name}}</div> + {{end}} + </div> + </div> + </div> + <div class="required field"> + <label for="host">{{ctx.Locale.Tr "admin.auths.host"}}</label> + <input id="host" name="host" value="{{.host}}" placeholder="mydomain.com"> + </div> + <div class="required field"> + <label for="port">{{ctx.Locale.Tr "admin.auths.port"}}</label> + <input id="port" name="port" value="{{.port}}" placeholder="636"> + </div> + <div class="has-tls inline field {{if not .HasTLS}}tw-hidden{{end}}"> + <div class="ui checkbox"> + <label><strong>{{ctx.Locale.Tr "admin.auths.skip_tls_verify"}}</strong></label> + <input name="skip_verify" type="checkbox" {{if .skip_verify}}checked{{end}}> + </div> + </div> + <div class="ldap field {{if not (eq .type 2)}}tw-hidden{{end}}"> + <label for="bind_dn">{{ctx.Locale.Tr "admin.auths.bind_dn"}}</label> + <input id="bind_dn" name="bind_dn" value="{{.bind_dn}}" placeholder="cn=Search,dc=mydomain,dc=com"> + </div> + <div class="ldap field {{if not (eq .type 2)}}tw-hidden{{end}}"> + <label for="bind_password">{{ctx.Locale.Tr "admin.auths.bind_password"}}</label> + <input id="bind_password" name="bind_password" type="password" autocomplete="off" value="{{.bind_password}}"> + </div> + <div class="binddnrequired {{if (eq .type 2)}}required{{end}} field"> + <label for="user_base">{{ctx.Locale.Tr "admin.auths.user_base"}}</label> + <input id="user_base" name="user_base" value="{{.user_base}}" placeholder="ou=Users,dc=mydomain,dc=com"> + </div> + <div class="dldap required field {{if not (eq .type 5)}}tw-hidden{{end}}"> + <label for="user_dn">{{ctx.Locale.Tr "admin.auths.user_dn"}}</label> + <input id="user_dn" name="user_dn" value="{{.user_dn}}" placeholder="uid=%s,ou=Users,dc=mydomain,dc=com"> + </div> + <div class="required field"> + <label for="filter">{{ctx.Locale.Tr "admin.auths.filter"}}</label> + <input id="filter" name="filter" value="{{.filter}}" placeholder="(&(objectClass=posixAccount)(|(uid=%[1]s)(mail=%[1]s)))"> + </div> + <div class="field"> + <label for="admin_filter">{{ctx.Locale.Tr "admin.auths.admin_filter"}}</label> + <input id="admin_filter" name="admin_filter" value="{{.admin_filter}}"> + </div> + <div class="field"> + <label for="restricted_filter">{{ctx.Locale.Tr "admin.auths.restricted_filter"}}</label> + <input id="restricted_filter" name="restricted_filter" value="{{.restricted_filter}}"> + <p class="help">{{ctx.Locale.Tr "admin.auths.restricted_filter_helper"}}</p> + </div> + <div class="field"> + <label for="attribute_username">{{ctx.Locale.Tr "admin.auths.attribute_username"}}</label> + <input id="attribute_username" name="attribute_username" value="{{.attribute_username}}" placeholder="{{ctx.Locale.Tr "admin.auths.attribute_username_placeholder"}}"> + </div> + <div class="field"> + <label for="attribute_name">{{ctx.Locale.Tr "admin.auths.attribute_name"}}</label> + <input id="attribute_name" name="attribute_name" value="{{.attribute_name}}"> + </div> + <div class="field"> + <label for="attribute_surname">{{ctx.Locale.Tr "admin.auths.attribute_surname"}}</label> + <input id="attribute_surname" name="attribute_surname" value="{{.attribute_surname}}"> + </div> + <div class="required field"> + <label for="attribute_mail">{{ctx.Locale.Tr "admin.auths.attribute_mail"}}</label> + <input id="attribute_mail" name="attribute_mail" value="{{.attribute_mail}}" placeholder="mail"> + </div> + <div class="field"> + <label for="default_domain_name">{{ctx.Locale.Tr "admin.auths.default_domain_name"}}</label> + <input id="default_domain_name" name="default_domain_name" value="{{.default_domain_name}}" placeholder="localhost.local"> + </div> + <div class="field"> + <label for="attribute_ssh_public_key">{{ctx.Locale.Tr "admin.auths.attribute_ssh_public_key"}}</label> + <input id="attribute_ssh_public_key" name="attribute_ssh_public_key" value="{{.attribute_ssh_public_key}}" placeholder="SshPublicKey"> + </div> + <div class="field"> + <label for="attribute_avatar">{{ctx.Locale.Tr "admin.auths.attribute_avatar"}}</label> + <input id="attribute_avatar" name="attribute_avatar" value="{{.attribute_avatar}}" placeholder="jpegPhoto"> + </div> + + <!-- ldap group begin --> + <div class="inline field"> + <div class="ui checkbox"> + <label><strong>{{ctx.Locale.Tr "admin.auths.enable_ldap_groups"}}</strong></label> + <input type="checkbox" name="groups_enabled" class="js-ldap-group-toggle" {{if .groups_enabled}}checked{{end}}> + </div> + </div> + <div id="ldap-group-options" class="ui segment secondary"> + <div class="field"> + <label>{{ctx.Locale.Tr "admin.auths.group_search_base"}}</label> + <input name="group_dn" value="{{.group_dn}}" placeholder="ou=group,dc=mydomain,dc=com"> + </div> + <div class="field"> + <label>{{ctx.Locale.Tr "admin.auths.group_attribute_list_users"}}</label> + <input name="group_member_uid" value="{{.group_member_uid}}" placeholder="memberUid"> + </div> + <div class="field"> + <label>{{ctx.Locale.Tr "admin.auths.user_attribute_in_group"}}</label> + <input name="user_uid" value="{{.user_uid}}" placeholder="uid"> + </div> + <div class="field"> + <label>{{ctx.Locale.Tr "admin.auths.verify_group_membership"}}</label> + <input name="group_filter" value="{{.group_filter}}" placeholder="(|(cn=gitea_users)(cn=admins))"> + </div> + <div class="field"> + <label>{{ctx.Locale.Tr "admin.auths.map_group_to_team"}}</label> + <textarea name="group_team_map" rows="5" placeholder='{"cn=my-group,cn=groups,dc=example,dc=org": {"MyForgejoOrganization": ["MyForgejoTeam1", "MyForgejoTeam2"]}}'>{{.group_team_map}}</textarea> + </div> + <div class="ui checkbox"> + <label>{{ctx.Locale.Tr "admin.auths.map_group_to_team_removal"}}</label> + <input name="group_team_map_removal" type="checkbox" {{if .group_team_map_removal}}checked{{end}}> + </div> + </div> + <!-- ldap group end --> + + <div class="ldap inline field {{if not (eq .type 2)}}tw-hidden{{end}}"> + <div class="ui checkbox"> + <label for="use_paged_search"><strong>{{ctx.Locale.Tr "admin.auths.use_paged_search"}}</strong></label> + <input id="use_paged_search" name="use_paged_search" class="use-paged-search" type="checkbox" {{if .use_paged_search}}checked{{end}}> + </div> + </div> + <div class="ldap field search-page-size required {{if or (not (eq .type 2)) (not .use_paged_search)}}tw-hidden{{end}}"> + <label for="search_page_size">{{ctx.Locale.Tr "admin.auths.search_page_size"}}</label> + <input id="search_page_size" name="search_page_size" value="{{.search_page_size}}"> + </div> + <div class="optional field"> + <div class="ui checkbox"> + <label for="skip_local_two_fa"><strong>{{ctx.Locale.Tr "admin.auths.skip_local_two_fa"}}</strong></label> + <input id="skip_local_two_fa" name="skip_local_two_fa" type="checkbox" {{if .skip_local_two_fa}}checked{{end}}> + <p class="help">{{ctx.Locale.Tr "admin.auths.skip_local_two_fa_helper"}}</p> + </div> + </div> + <div class="inline field"> + <div class="ui checkbox"> + <label for="allow_deactivate_all"><strong>{{ctx.Locale.Tr "admin.auths.allow_deactivate_all"}}</strong></label> + <input id="allow_deactivate_all" name="allow_deactivate_all" type="checkbox" {{if .allow_deactivate_all}}checked{{end}}> + </div> + </div> +</div> diff --git a/templates/admin/auth/source/oauth.tmpl b/templates/admin/auth/source/oauth.tmpl new file mode 100644 index 0000000..0560cc8 --- /dev/null +++ b/templates/admin/auth/source/oauth.tmpl @@ -0,0 +1,109 @@ +<div class="oauth2 field {{if not (eq .type 6)}}tw-hidden{{end}}"> + <div class="inline required field"> + <label>{{ctx.Locale.Tr "admin.auths.oauth2_provider"}}</label> + <div class="ui selection type dropdown"> + <input type="hidden" id="oauth2_provider" name="oauth2_provider" value="{{.oauth2_provider}}"> + <div class="text">{{.oauth2_provider}}</div> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="menu"> + {{range .OAuth2Providers}} + <div class="item" data-value="{{.Name}}">{{.DisplayName}}</div> + {{end}} + </div> + </div> + </div> + <div class="required field"> + <label for="oauth2_key">{{ctx.Locale.Tr "admin.auths.oauth2_clientID"}}</label> + <input id="oauth2_key" name="oauth2_key" value="{{.oauth2_key}}"> + </div> + <div class="required field"> + <label for="oauth2_secret">{{ctx.Locale.Tr "admin.auths.oauth2_clientSecret"}}</label> + <input id="oauth2_secret" name="oauth2_secret" value="{{.oauth2_secret}}"> + </div> + <div class="optional field"> + <label for="oauth2_icon_url">{{ctx.Locale.Tr "admin.auths.oauth2_icon_url"}}</label> + <input id="oauth2_icon_url" name="oauth2_icon_url" value="{{.oauth2_icon_url}}"> + </div> + <div class="open_id_connect_auto_discovery_url required field{{if .Err_DiscoveryURL}} error{{end}}"> + <label for="open_id_connect_auto_discovery_url">{{ctx.Locale.Tr "admin.auths.openIdConnectAutoDiscoveryURL"}}</label> + <input id="open_id_connect_auto_discovery_url" name="open_id_connect_auto_discovery_url" value="{{.open_id_connect_auto_discovery_url}}"> + </div> + <div class="optional field"> + <div class="ui checkbox"> + <label for="skip_local_two_fa"><strong>{{ctx.Locale.Tr "admin.auths.skip_local_two_fa"}}</strong></label> + <input id="skip_local_two_fa" name="skip_local_two_fa" type="checkbox" {{if .skip_local_two_fa}}checked{{end}}> + <p class="help">{{ctx.Locale.Tr "admin.auths.skip_local_two_fa_helper"}}</p> + </div> + </div> + + <div class="oauth2_use_custom_url inline field"> + <div class="ui checkbox"> + <label><strong>{{ctx.Locale.Tr "admin.auths.oauth2_use_custom_url"}}</strong></label> + <input id="oauth2_use_custom_url" name="oauth2_use_custom_url" type="checkbox"> + </div> + </div> + <div class="oauth2_use_custom_url_field oauth2_auth_url required field"> + <label for="oauth2_auth_url">{{ctx.Locale.Tr "admin.auths.oauth2_authURL"}}</label> + <input id="oauth2_auth_url" name="oauth2_auth_url" value="{{.oauth2_auth_url}}"> + </div> + <div class="oauth2_use_custom_url_field oauth2_token_url required field"> + <label for="oauth2_token_url">{{ctx.Locale.Tr "admin.auths.oauth2_tokenURL"}}</label> + <input id="oauth2_token_url" name="oauth2_token_url" value="{{.oauth2_token_url}}"> + </div> + <div class="oauth2_use_custom_url_field oauth2_profile_url required field"> + <label for="oauth2_profile_url">{{ctx.Locale.Tr "admin.auths.oauth2_profileURL"}}</label> + <input id="oauth2_profile_url" name="oauth2_profile_url" value="{{.oauth2_profile_url}}"> + </div> + <div class="oauth2_use_custom_url_field oauth2_email_url required field"> + <label for="oauth2_email_url">{{ctx.Locale.Tr "admin.auths.oauth2_emailURL"}}</label> + <input id="oauth2_email_url" name="oauth2_email_url" value="{{.oauth2_email_url}}"> + </div> + <div class="oauth2_use_custom_url_field oauth2_tenant required field"> + <label for="oauth2_tenant">{{ctx.Locale.Tr "admin.auths.oauth2_tenant"}}</label> + <input id="oauth2_tenant" name="oauth2_tenant" value="{{.oauth2_tenant}}"> + </div> + + {{range .OAuth2Providers}}{{if .CustomURLSettings}} + <input id="{{.Name}}_customURLSettings" type="hidden" data-required="{{.CustomURLSettings.Required}}" data-available="true"> + <input id="{{.Name}}_token_url" value="{{.CustomURLSettings.TokenURL.Value}}" data-available="{{.CustomURLSettings.TokenURL.Available}}" data-required="{{.CustomURLSettings.TokenURL.Required}}" type="hidden"> + <input id="{{.Name}}_auth_url" value="{{.CustomURLSettings.AuthURL.Value}}" data-available="{{.CustomURLSettings.AuthURL.Available}}" data-required="{{.CustomURLSettings.AuthURL.Required}}" type="hidden"> + <input id="{{.Name}}_profile_url" value="{{.CustomURLSettings.ProfileURL.Value}}" data-available="{{.CustomURLSettings.ProfileURL.Available}}" data-required="{{.CustomURLSettings.ProfileURL.Required}}" type="hidden"> + <input id="{{.Name}}_email_url" value="{{.CustomURLSettings.EmailURL.Value}}" data-available="{{.CustomURLSettings.EmailURL.Available}}" data-required="{{.CustomURLSettings.EmailURL.Required}}" type="hidden"> + <input id="{{.Name}}_tenant" value="{{.CustomURLSettings.Tenant.Value}}" data-available="{{.CustomURLSettings.Tenant.Available}}" data-required="{{.CustomURLSettings.Tenant.Required}}" type="hidden"> + {{end}}{{end}} + + <div class="field"> + <label for="oauth2_scopes">{{ctx.Locale.Tr "admin.auths.oauth2_scopes"}}</label> + <input id="oauth2_scopes" name="oauth2_scopes" value="{{.oauth2_scopes}}"> + </div> + <div class="field"> + <label for="oauth2_required_claim_name">{{ctx.Locale.Tr "admin.auths.oauth2_required_claim_name"}}</label> + <input id="oauth2_required_claim_name" name="oauth2_required_claim_name" value="{{.oauth2_required_claim_name}}"> + <p class="help">{{ctx.Locale.Tr "admin.auths.oauth2_required_claim_name_helper"}}</p> + </div> + <div class="field"> + <label for="oauth2_required_claim_value">{{ctx.Locale.Tr "admin.auths.oauth2_required_claim_value"}}</label> + <input id="oauth2_required_claim_value" name="oauth2_required_claim_value" value="{{.oauth2_required_claim_value}}"> + <p class="help">{{ctx.Locale.Tr "admin.auths.oauth2_required_claim_value_helper"}}</p> + </div> + <div class="field"> + <label for="oauth2_group_claim_name">{{ctx.Locale.Tr "admin.auths.oauth2_group_claim_name"}}</label> + <input id="oauth2_group_claim_name" name="oauth2_group_claim_name" value="{{.oauth2_group_claim_name}}"> + </div> + <div class="field"> + <label for="oauth2_admin_group">{{ctx.Locale.Tr "admin.auths.oauth2_admin_group"}}</label> + <input id="oauth2_admin_group" name="oauth2_admin_group" value="{{.oauth2_admin_group}}"> + </div> + <div class="field"> + <label for="oauth2_restricted_group">{{ctx.Locale.Tr "admin.auths.oauth2_restricted_group"}}</label> + <input id="oauth2_restricted_group" name="oauth2_restricted_group" value="{{.oauth2_restricted_group}}"> + </div> + <div class="field"> + <label>{{ctx.Locale.Tr "admin.auths.oauth2_map_group_to_team"}}</label> + <textarea name="oauth2_group_team_map" rows="5" placeholder='{"Developer": {"MyForgejoOrganization": ["MyForgejoTeam1", "MyForgejoTeam2"]}}'>{{.oauth2_group_team_map}}</textarea> + </div> + <div class="ui checkbox"> + <label>{{ctx.Locale.Tr "admin.auths.oauth2_map_group_to_team_removal"}}</label> + <input name="oauth2_group_team_map_removal" type="checkbox" {{if .oauth2_group_team_map_removal}}checked{{end}}> + </div> +</div> diff --git a/templates/admin/auth/source/smtp.tmpl b/templates/admin/auth/source/smtp.tmpl new file mode 100644 index 0000000..31195ac --- /dev/null +++ b/templates/admin/auth/source/smtp.tmpl @@ -0,0 +1,59 @@ +<div class="smtp field {{if not (eq .type 3)}}tw-hidden{{end}}"> + <div class="inline required field"> + <label>{{ctx.Locale.Tr "admin.auths.smtp_auth"}}</label> + <div class="ui selection type dropdown"> + <input type="hidden" id="smtp_auth" name="smtp_auth" value="{{.smtp_auth}}"> + <div class="text">{{.smtp_auth}}</div> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="menu"> + {{range .SMTPAuths}} + <div class="item" data-value="{{.}}">{{.}}</div> + {{end}} + </div> + </div> + </div> + <div class="required field"> + <label for="smtp_host">{{ctx.Locale.Tr "admin.auths.smtphost"}}</label> + <input id="smtp_host" name="smtp_host" value="{{.smtp_host}}"> + </div> + <div class="required field"> + <label for="smtp_port">{{ctx.Locale.Tr "admin.auths.smtpport"}}</label> + <input id="smtp_port" name="smtp_port" value="{{.smtp_port}}"> + </div> + <div class="inline field"> + <div class="ui checkbox"> + <label for="force_smtps"><strong>{{ctx.Locale.Tr "admin.auths.force_smtps"}}</strong></label> + <input id="force_smtps" name="force_smtps" type="checkbox" {{if .force_smtps}}checked{{end}}> + <p class="help">{{ctx.Locale.Tr "admin.auths.force_smtps_helper"}}</p> + </div> + </div> + <div class="inline field"> + <div class="ui checkbox"> + <label><strong>{{ctx.Locale.Tr "admin.auths.skip_tls_verify"}}</strong></label> + <input name="skip_verify" type="checkbox" {{if .skip_verify}}checked{{end}}> + </div> + </div> + <div class="field"> + <label for="helo_hostname">{{ctx.Locale.Tr "admin.auths.helo_hostname"}}</label> + <input id="helo_hostname" name="helo_hostname" value="{{.helo_hostname}}"> + <p class="help">{{ctx.Locale.Tr "admin.auths.helo_hostname_helper"}}</p> + </div> + <div class="inline field"> + <div class="ui checkbox"> + <label for="disable_helo"><strong>{{ctx.Locale.Tr "admin.auths.disable_helo"}}</strong></label> + <input id="disable_helo" name="disable_helo" type="checkbox" {{if .disable_helo}}checked{{end}}> + </div> + </div> + <div class="field"> + <label for="allowed_domains">{{ctx.Locale.Tr "admin.auths.allowed_domains"}}</label> + <input id="allowed_domains" name="allowed_domains" value="{{.allowed_domains}}"> + <p class="help">{{ctx.Locale.Tr "admin.auths.allowed_domains_helper"}}</p> + </div> + <div class="optional field"> + <div class="ui checkbox"> + <label for="skip_local_two_fa"><strong>{{ctx.Locale.Tr "admin.auths.skip_local_two_fa"}}</strong></label> + <input id="skip_local_two_fa" name="skip_local_two_fa" type="checkbox" {{if .skip_local_two_fa}}checked{{end}}> + <p class="help">{{ctx.Locale.Tr "admin.auths.skip_local_two_fa_helper"}}</p> + </div> + </div> +</div> diff --git a/templates/admin/auth/source/sspi.tmpl b/templates/admin/auth/source/sspi.tmpl new file mode 100644 index 0000000..6a3f00f --- /dev/null +++ b/templates/admin/auth/source/sspi.tmpl @@ -0,0 +1,43 @@ +<div class="sspi field {{if not (eq .type 7)}}tw-hidden{{end}}"> + <div class="field"> + <div class="ui checkbox"> + <label for="sspi_auto_create_users"><strong>{{ctx.Locale.Tr "admin.auths.sspi_auto_create_users"}}</strong></label> + <input id="sspi_auto_create_users" name="sspi_auto_create_users" class="sspi-auto-create-users" type="checkbox" {{if .SSPIAutoCreateUsers}}checked{{end}}> + <p class="help">{{ctx.Locale.Tr "admin.auths.sspi_auto_create_users_helper"}}</p> + </div> + </div> + <div class="field"> + <div class="ui checkbox"> + <label for="sspi_auto_activate_users"><strong>{{ctx.Locale.Tr "admin.auths.sspi_auto_activate_users"}}</strong></label> + <input id="sspi_auto_activate_users" name="sspi_auto_activate_users" class="sspi-auto-activate-users" type="checkbox" {{if .SSPIAutoActivateUsers}}checked{{end}}> + <p class="help">{{ctx.Locale.Tr "admin.auths.sspi_auto_activate_users_helper"}}</p> + </div> + </div> + <div class="field"> + <div class="ui checkbox"> + <label for="sspi_strip_domain_names"><strong>{{ctx.Locale.Tr "admin.auths.sspi_strip_domain_names"}}</strong></label> + <input id="sspi_strip_domain_names" name="sspi_strip_domain_names" class="sspi-strip-domain-names" type="checkbox" {{if .SSPIStripDomainNames}}checked{{end}}> + <p class="help">{{ctx.Locale.Tr "admin.auths.sspi_strip_domain_names_helper"}}</p> + </div> + </div> + <div class="required field"> + <label for="sspi_separator_replacement">{{ctx.Locale.Tr "admin.auths.sspi_separator_replacement"}}</label> + <input id="sspi_separator_replacement" name="sspi_separator_replacement" value="{{.SSPISeparatorReplacement}}"> + <p class="help">{{ctx.Locale.Tr "admin.auths.sspi_separator_replacement_helper"}}</p> + </div> + <div class="field"> + <label for="sspi_default_language">{{ctx.Locale.Tr "admin.auths.sspi_default_language"}}</label> + <div class="ui language selection dropdown" id="sspi_default_language"> + <input name="sspi_default_language" type="hidden" value="{{.SSPIDefaultLanguage}}"> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="text">{{range .AllLangs}}{{if eq $.SSPIDefaultLanguage .Lang}}{{.Name}}{{end}}{{end}}</div> + <div class="menu"> + <div class="item{{if not $.SSPIDefaultLanguage}} active selected{{end}}" data-value="">-</div> + {{range .AllLangs}} + <div class="item{{if eq $.SSPIDefaultLanguage .Lang}} active selected{{end}}" data-value="{{.Lang}}">{{.Name}}</div> + {{end}} + </div> + </div> + <p class="help">{{ctx.Locale.Tr "admin.auths.sspi_default_language_helper"}}</p> + </div> +</div> diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl new file mode 100644 index 0000000..8f2b1c1 --- /dev/null +++ b/templates/admin/config.tmpl @@ -0,0 +1,355 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin config")}} + <div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.config.server_config"}} + </h4> + <div class="ui attached table segment"> + <dl class="admin-dl-horizontal"> + <dt>{{ctx.Locale.Tr "admin.config.app_name"}}</dt> + <dd>{{AppName}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.app_slogan"}}</dt> + <dd>{{AppSlogan}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.app_ver"}}</dt> + <dd>{{AppVer}}{{.AppBuiltWith}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.custom_conf"}}</dt> + <dd>{{.CustomConf}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.app_url"}}</dt> + <dd>{{.AppUrl}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.domain"}}</dt> + <dd>{{.Domain}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.offline_mode"}}</dt> + <dd>{{if .OfflineMode}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.disable_router_log"}}</dt> + <dd>{{if .DisableRouterLog}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + + <div class="divider"></div> + + <dt>{{ctx.Locale.Tr "admin.config.run_user"}}</dt> + <dd>{{.RunUser}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.run_mode"}}</dt> + <dd>{{.RunMode}}</dd> + + <div class="divider"></div> + + <dt>{{ctx.Locale.Tr "admin.config.git_version"}}</dt> + <dd>{{.GitVersion}}</dd> + + <div class="divider"></div> + + <dt>{{ctx.Locale.Tr "admin.config.app_data_path"}}</dt> + <dd>{{.AppDataPath}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.repo_root_path"}}</dt> + <dd>{{.RepoRootPath}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.custom_file_root_path"}}</dt> + <dd>{{.CustomRootPath}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.log_file_root_path"}}</dt> + <dd>{{.LogRootPath}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.script_type"}}</dt> + <dd>{{.ScriptType}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.reverse_auth_user"}}</dt> + <dd>{{.ReverseProxyAuthUser}}</dd> + </dl> + </div> + + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.config.ssh_config"}} + </h4> + <div class="ui attached table segment"> + <dl class="admin-dl-horizontal"> + <dt>{{ctx.Locale.Tr "admin.config.ssh_enabled"}}</dt> + <dd>{{if not .SSH.Disabled}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + {{if not .SSH.Disabled}} + <dt>{{ctx.Locale.Tr "admin.config.ssh_start_builtin_server"}}</dt> + <dd>{{if .SSH.StartBuiltinServer}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.ssh_domain"}}</dt> + <dd>{{.SSH.Domain}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.ssh_port"}}</dt> + <dd>{{.SSH.Port}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.ssh_listen_port"}}</dt> + <dd>{{.SSH.ListenPort}}</dd> + + {{if not .SSH.StartBuiltinServer}} + <dt>{{ctx.Locale.Tr "admin.config.ssh_root_path"}}</dt> + <dd>{{.SSH.RootPath}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.ssh_key_test_path"}}</dt> + <dd>{{.SSH.KeyTestPath}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.ssh_keygen_path"}}</dt> + <dd>{{.SSH.KeygenPath}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.ssh_minimum_key_size_check"}}</dt> + <dd>{{if .SSH.MinimumKeySizeCheck}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + {{if .SSH.MinimumKeySizeCheck}} + <dt>{{ctx.Locale.Tr "admin.config.ssh_minimum_key_sizes"}}</dt> + <dd>{{.SSH.MinimumKeySizes}}</dd> + {{end}} + {{end}} + {{end}} + </dl> + </div> + + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.config.lfs_config"}} + </h4> + <div class="ui attached table segment"> + <dl class="admin-dl-horizontal"> + <dt>{{ctx.Locale.Tr "admin.config.lfs_enabled"}}</dt> + <dd>{{if .LFS.StartServer}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + {{if .LFS.StartServer}} + <dt>{{ctx.Locale.Tr "admin.config.lfs_content_path"}}</dt> + <dd>{{JsonUtils.EncodeToString .LFS.Storage.ToShadowCopy}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.lfs_http_auth_expiry"}}</dt> + <dd>{{.LFS.HTTPAuthExpiry}}</dd> + {{end}} + </dl> + </div> + + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.config.db_config"}} + </h4> + <div class="ui attached table segment"> + <dl class="admin-dl-horizontal"> + <dt>{{ctx.Locale.Tr "admin.config.db_type"}}</dt> + <dd>{{.DbCfg.Type}}</dd> + {{if not (eq .DbCfg.Type "sqlite3")}} + <dt>{{ctx.Locale.Tr "admin.config.db_host"}}</dt> + <dd>{{if .DbCfg.Host}}{{.DbCfg.Host}}{{else}}-{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.db_name"}}</dt> + <dd>{{if .DbCfg.Name}}{{.DbCfg.Name}}{{else}}-{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.db_user"}}</dt> + <dd>{{if .DbCfg.User}}{{.DbCfg.User}}{{else}}-{{end}}</dd> + {{end}} + {{if eq .DbCfg.Type "postgres"}} + <dt>{{ctx.Locale.Tr "admin.config.db_schema"}}</dt> + <dd>{{if .DbCfg.Schema}}{{.DbCfg.Schema}}{{else}}-{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.db_ssl_mode"}}</dt> + <dd>{{if .DbCfg.SSLMode}}{{.DbCfg.SSLMode}}{{else}}-{{end}}</dd> + {{end}} + {{if eq .DbCfg.Type "sqlite3"}} + <dt>{{ctx.Locale.Tr "admin.config.db_path"}}</dt> + <dd>{{if .DbCfg.Path}}{{.DbCfg.Path}}{{else}}-{{end}}</dd> + {{end}} + </dl> + </div> + + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.config.service_config"}} + </h4> + <div class="ui attached table segment"> + <dl class="admin-dl-horizontal"> + <dt>{{ctx.Locale.Tr "admin.config.register_email_confirm"}}</dt> + <dd>{{if .Service.RegisterEmailConfirm}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.disable_register"}}</dt> + <dd>{{if .Service.DisableRegistration}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.allow_only_internal_registration"}}</dt> + <dd>{{if .Service.AllowOnlyInternalRegistration}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.allow_only_external_registration"}}</dt> + <dd>{{if .Service.AllowOnlyExternalRegistration}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.show_registration_button"}}</dt> + <dd>{{if .Service.ShowRegistrationButton}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.enable_openid_signup"}}</dt> + <dd>{{if .Service.EnableOpenIDSignUp}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.enable_openid_signin"}}</dt> + <dd>{{if .Service.EnableOpenIDSignIn}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.require_sign_in_view"}}</dt> + <dd>{{if .Service.RequireSignInView}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.mail_notify"}}</dt> + <dd>{{if .Service.EnableNotifyMail}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.enable_captcha"}}</dt> + <dd>{{if .Service.EnableCaptcha}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.default_keep_email_private"}}</dt> + <dd>{{if .Service.DefaultKeepEmailPrivate}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.default_allow_create_organization"}}</dt> + <dd>{{if .Service.DefaultAllowCreateOrganization}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.allow_dots_in_usernames"}}</dt> + <dd>{{if .Service.AllowDotsInUsernames}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.enable_timetracking"}}</dt> + <dd>{{if .Service.EnableTimetracking}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + {{if .Service.EnableTimetracking}} + <dt>{{ctx.Locale.Tr "admin.config.default_enable_timetracking"}}</dt> + <dd>{{if .Service.DefaultEnableTimetracking}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.default_allow_only_contributors_to_track_time"}}</dt> + <dd>{{if .Service.DefaultAllowOnlyContributorsToTrackTime}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + {{end}} + <dt>{{ctx.Locale.Tr "admin.config.default_visibility_organization"}}</dt> + <dd>{{.Service.DefaultOrgVisibility}}</dd> + + <dt>{{ctx.Locale.Tr "admin.config.no_reply_address"}}</dt> + <dd>{{if .Service.NoReplyAddress}}{{.Service.NoReplyAddress}}{{else}}-{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.default_enable_dependencies"}}</dt> + <dd>{{if .Service.DefaultEnableDependencies}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <div class="divider"></div> + <dt>{{ctx.Locale.Tr "admin.config.active_code_lives"}}</dt> + <dd>{{.Service.ActiveCodeLives}} {{ctx.Locale.Tr "tool.raw_minutes"}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.reset_password_code_lives"}}</dt> + <dd>{{.Service.ResetPwdCodeLives}} {{ctx.Locale.Tr "tool.raw_minutes"}}</dd> + </dl> + </div> + + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.config.webhook_config"}} + </h4> + <div class="ui attached table segment"> + <dl class="admin-dl-horizontal"> + <dt>{{ctx.Locale.Tr "admin.config.queue_length"}}</dt> + <dd>{{.Webhook.QueueLength}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.deliver_timeout"}}</dt> + <dd>{{.Webhook.DeliverTimeout}} {{ctx.Locale.Tr "tool.raw_seconds"}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.skip_tls_verify"}}</dt> + <dd>{{if .Webhook.SkipTLSVerify}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + </dl> + </div> + + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.config.mailer_config"}} + </h4> + <div class="ui attached table segment"> + <dl class="admin-dl-horizontal"> + <dt>{{ctx.Locale.Tr "admin.config.mailer_enabled"}}</dt> + <dd>{{if .MailerEnabled}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + {{if .MailerEnabled}} + <dt>{{ctx.Locale.Tr "admin.config.mailer_name"}}</dt> + <dd>{{.Mailer.Name}}</dd> + {{if eq .Mailer.Protocol "sendmail"}} + <dt>{{ctx.Locale.Tr "admin.config.mailer_use_sendmail"}}</dt> + <dd>{{svg "octicon-check"}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.mailer_sendmail_path"}}</dt> + <dd>{{.Mailer.SendmailPath}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.mailer_sendmail_args"}}</dt> + <dd>{{.Mailer.SendmailArgs}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.mailer_sendmail_timeout"}}</dt> + <dd>{{.Mailer.SendmailTimeout}} {{ctx.Locale.Tr "tool.raw_seconds"}}</dd> + {{else if eq .Mailer.Protocol "dummy"}} + <dt>{{ctx.Locale.Tr "admin.config.mailer_use_dummy"}}</dt> + <dd>{{svg "octicon-check"}}</dd> + {{else}}{{/* SMTP family */}} + <dt>{{ctx.Locale.Tr "admin.config.mailer_protocol"}}</dt> + <dd>{{.Mailer.Protocol}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.mailer_enable_helo"}}</dt> + <dd>{{if .Mailer.EnableHelo}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.mailer_smtp_addr"}}</dt> + <dd>{{.Mailer.SMTPAddr}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.mailer_smtp_port"}}</dt> + <dd>{{.Mailer.SMTPPort}}</dd> + {{end}} + <dt>{{ctx.Locale.Tr "admin.config.mailer_user"}}</dt> + <dd>{{if .Mailer.User}}{{.Mailer.User}}{{else}}(empty){{end}}</dd> + <div class="divider"></div> + <dt class="tw-py-1 tw-flex tw-items-center">{{ctx.Locale.Tr "admin.config.send_test_mail"}}</dt> + <dd class="tw-py-0"> + <form class="ui form ignore-dirty" action="{{AppSubUrl}}/admin/config/test_mail" method="post"> + {{.CsrfTokenHtml}} + <div class="ui tiny input"> + <input type="email" name="email" placeholder="{{ctx.Locale.Tr "admin.config.test_email_placeholder"}}" size="29" required> + </div> + <button class="ui tiny primary button">{{ctx.Locale.Tr "admin.config.send_test_mail_submit"}}</button> + </form> + </dd> + {{end}} + </dl> + </div> + + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.config.cache_config"}} + </h4> + <div class="ui attached table segment"> + <dl class="admin-dl-horizontal"> + <dt>{{ctx.Locale.Tr "admin.config.cache_adapter"}}</dt> + <dd>{{.CacheAdapter}}</dd> + {{if eq .CacheAdapter "memory"}} + <dt>{{ctx.Locale.Tr "admin.config.cache_interval"}}</dt> + <dd>{{.CacheInterval}} {{ctx.Locale.Tr "tool.raw_seconds"}}</dd> + {{end}} + {{if .CacheConn}} + <dt>{{ctx.Locale.Tr "admin.config.cache_conn"}}</dt> + <dd><code>{{.CacheConn}}</code></dd> + <dt>{{ctx.Locale.Tr "admin.config.cache_item_ttl"}}</dt> + <dd><code>{{.CacheItemTTL}}</code></dd> + {{end}} + <div class="divider"></div> + <dt class="tw-py-1 tw-flex tw-items-center">{{ctx.Locale.Tr "admin.config.cache_test"}}</dt> + <dd class="tw-py-0"> + <form class="ui form ignore-dirty" action="{{AppSubUrl}}/admin/config/test_cache" method="post"> + {{.CsrfTokenHtml}} + <button class="ui tiny primary button">{{ctx.Locale.Tr "test"}}</button> + </form> + </dd> + </dl> + </div> + + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.config.session_config"}} + </h4> + <div class="ui attached table segment"> + <dl class="admin-dl-horizontal"> + <dt>{{ctx.Locale.Tr "admin.config.session_provider"}}</dt> + <dd>{{.SessionConfig.Provider}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.provider_config"}}</dt> + <dd><code>{{if .SessionConfig.ProviderConfig}}{{.SessionConfig.ProviderConfig}}{{else}}-{{end}}</code></dd> + <dt>{{ctx.Locale.Tr "admin.config.cookie_name"}}</dt> + <dd>{{.SessionConfig.CookieName}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.gc_interval_time"}}</dt> + <dd>{{.SessionConfig.Gclifetime}} {{ctx.Locale.Tr "tool.raw_seconds"}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.session_life_time"}}</dt> + <dd>{{.SessionConfig.Maxlifetime}} {{ctx.Locale.Tr "tool.raw_seconds"}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.https_only"}}</dt> + <dd>{{if .SessionConfig.Secure}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + </dl> + </div> + + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.config.git_config"}} + </h4> + <div class="ui attached table segment"> + <dl class="admin-dl-horizontal"> + <dt>{{ctx.Locale.Tr "admin.config.git_disable_diff_highlight"}}</dt> + <dd>{{if .Git.DisableDiffHighlight}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.git_max_diff_lines"}}</dt> + <dd>{{.Git.MaxGitDiffLines}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.git_max_diff_line_characters"}}</dt> + <dd>{{.Git.MaxGitDiffLineCharacters}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.git_max_diff_files"}}</dt> + <dd>{{.Git.MaxGitDiffFiles}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.git_gc_args"}}</dt> + <dd><code>{{.Git.GCArgs}}</code></dd> + + <div class="divider"></div> + + <dt>{{ctx.Locale.Tr "admin.config.git_migrate_timeout"}}</dt> + <dd>{{.Git.Timeout.Migrate}} {{ctx.Locale.Tr "tool.raw_seconds"}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.git_mirror_timeout"}}</dt> + <dd>{{.Git.Timeout.Mirror}} {{ctx.Locale.Tr "tool.raw_seconds"}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.git_clone_timeout"}}</dt> + <dd>{{.Git.Timeout.Clone}} {{ctx.Locale.Tr "tool.raw_seconds"}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.git_pull_timeout"}}</dt> + <dd>{{.Git.Timeout.Pull}} {{ctx.Locale.Tr "tool.raw_seconds"}}</dd> + <dt>{{ctx.Locale.Tr "admin.config.git_gc_timeout"}}</dt> + <dd>{{.Git.Timeout.GC}} {{ctx.Locale.Tr "tool.raw_seconds"}}</dd> + </dl> + </div> + + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.config.log_config"}} + </h4> + <div class="ui attached table segment"> + <dl class="admin-dl-horizontal"> + {{if .Loggers.xorm.IsEnabled}} + <dt>{{ctx.Locale.Tr "admin.config.xorm_log_sql"}}</dt> + <dd>{{if $.LogSQL}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</dd> + {{end}} + + {{if .Loggers.access.IsEnabled}} + <dt>{{ctx.Locale.Tr "admin.config.access_log_template"}}</dt> + <dd><code>{{$.AccessLogTemplate}}</code></dd> + {{end}} + + {{range $loggerName, $loggerDetail := .Loggers}} + <dt>{{ctx.Locale.Tr "admin.config.logger_name_fmt" $loggerName}}</dt> + {{if $loggerDetail.IsEnabled}} + <dd><pre class="tw-m-0">{{$loggerDetail.EventWriters | JsonUtils.EncodeToString | JsonUtils.PrettyIndent}}</pre></dd> + {{else}} + <dd>{{ctx.Locale.Tr "admin.config.disabled_logger"}}</dd> + {{end}} + {{end}} + </dl> + </div> + </div> +{{template "admin/layout_footer" .}} diff --git a/templates/admin/config_settings.tmpl b/templates/admin/config_settings.tmpl new file mode 100644 index 0000000..02ab5fd --- /dev/null +++ b/templates/admin/config_settings.tmpl @@ -0,0 +1,42 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin config")}} +<h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.config.picture_config"}} +</h4> +<div class="ui attached table segment"> + <dl class="admin-dl-horizontal"> + <dt>{{ctx.Locale.Tr "admin.config.disable_gravatar"}}</dt> + <dd> + <div class="ui toggle checkbox" data-tooltip-content="{{ctx.Locale.Tr "admin.config.disable_gravatar"}}"> + <input type="checkbox" data-config-dyn-key="picture.disable_gravatar" {{if .SystemConfig.Picture.DisableGravatar.Value ctx}}checked{{end}}><label></label> + </div> + </dd> + <div class="divider"></div> + <dt>{{ctx.Locale.Tr "admin.config.enable_federated_avatar"}}</dt> + <dd> + <div class="ui toggle checkbox" data-tooltip-content="{{ctx.Locale.Tr "admin.config.enable_federated_avatar"}}"> + <input type="checkbox" data-config-dyn-key="picture.enable_federated_avatar" {{if .SystemConfig.Picture.EnableFederatedAvatar.Value ctx}}checked{{end}}><label></label> + </div> + </dd> + </dl> +</div> + +<h4 class="ui top attached header"> + {{ctx.Locale.Tr "repository"}} +</h4> +<div class="ui attached segment"> + <form class="ui form form-fetch-action" method="post" action="{{AppSubUrl}}/admin/config?key={{.SystemConfig.Repository.OpenWithEditorApps.DynKey}}"> + <div class="field"> + <details> + <summary>{{ctx.Locale.Tr "admin.config.open_with_editor_app_help"}}</summary> + <pre class="tw-px-4">{{.DefaultOpenWithEditorAppsString}}</pre> + </details> + </div> + <div class="field"> + <textarea name="value">{{(.SystemConfig.Repository.OpenWithEditorApps.Value ctx).ToTextareaString}}</textarea> + </div> + <div class="field"> + <button class="ui primary button">{{ctx.Locale.Tr "save"}}</button> + </div> + </form> +</div> +{{template "admin/layout_footer" .}} diff --git a/templates/admin/cron.tmpl b/templates/admin/cron.tmpl new file mode 100644 index 0000000..3cb6414 --- /dev/null +++ b/templates/admin/cron.tmpl @@ -0,0 +1,39 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin monitor")}} +<div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.monitor.cron"}} + </h4> + <div class="ui attached table segment"> + <form method="post" action="{{AppSubUrl}}/admin"> + <table class="ui very basic striped table unstackable tw-mb-0"> + <thead> + <tr> + <th></th> + <th>{{ctx.Locale.Tr "admin.monitor.name"}}</th> + <th>{{ctx.Locale.Tr "admin.monitor.schedule"}}</th> + <th>{{ctx.Locale.Tr "admin.monitor.next"}}</th> + <th>{{ctx.Locale.Tr "admin.monitor.previous"}}</th> + <th>{{ctx.Locale.Tr "admin.monitor.execute_times"}}</th> + <th>{{ctx.Locale.Tr "admin.monitor.last_execution_result"}}</th> + </tr> + </thead> + <tbody> + {{range .Entries}} + <tr> + <td><button type="submit" class="ui primary button" name="op" value="{{.Name}}" title="{{ctx.Locale.Tr "admin.dashboard.operation_run"}}">{{svg "octicon-triangle-right"}}</button></td> + <td>{{ctx.Locale.Tr (printf "admin.dashboard.%s" .Name)}}</td> + <td>{{.Spec}}</td> + <td>{{DateTime "full" .Next}}</td> + <td>{{if gt .Prev.Year 1}}{{DateTime "full" .Prev}}{{else}}-{{end}}</td> + <td>{{.ExecTimes}}</td> + <td {{if ne .Status ""}}data-tooltip-content="{{.FormatLastMessage ctx.Locale}}"{{end}} >{{if eq .Status ""}}—{{else if eq .Status "finished"}}{{svg "octicon-check" 16}}{{else}}{{svg "octicon-x" 16}}{{end}}</td> + </tr> + {{end}} + </tbody> + </table> + <input type="hidden" name="from" value="monitor"> + {{.CsrfTokenHtml}} + </form> + </div> +</div> +{{template "admin/layout_footer" .}} diff --git a/templates/admin/dashboard.tmpl b/templates/admin/dashboard.tmpl new file mode 100644 index 0000000..b61de66 --- /dev/null +++ b/templates/admin/dashboard.tmpl @@ -0,0 +1,84 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin dashboard")}} + <div class="admin-setting-content"> + {{if .NeedUpdate}} + <div class="ui negative message flash-error"> + <p>{{ctx.Locale.Tr "admin.dashboard.new_version_hint" .RemoteVersion AppVer "https://forgejo.org/news"}}</p> + </div> + {{end}} + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.dashboard.operations"}} + </h4> + <div class="ui attached table segment"> + <form method="post" action="{{AppSubUrl}}/admin"> + {{.CsrfTokenHtml}} + <table class="ui very basic table tw-mt-0 tw-px-4"> + <tbody> + <tr> + <td>{{ctx.Locale.Tr "admin.dashboard.delete_inactive_accounts"}}</td> + <td class="text right"><button type="submit" class="ui primary button" name="op" value="delete_inactive_accounts">{{svg "octicon-play"}} {{ctx.Locale.Tr "admin.dashboard.operation_run"}}</button></td> + </tr> + <tr> + <td>{{ctx.Locale.Tr "admin.dashboard.delete_repo_archives"}}</td> + <td class="text right"><button type="submit" class="ui primary button" name="op" value="delete_repo_archives">{{svg "octicon-play"}} {{ctx.Locale.Tr "admin.dashboard.operation_run"}}</button></td> + </tr> + <tr> + <td>{{ctx.Locale.Tr "admin.dashboard.delete_missing_repos"}}</td> + <td class="text right"><button type="submit" class="ui primary button" name="op" value="delete_missing_repos">{{svg "octicon-play"}} {{ctx.Locale.Tr "admin.dashboard.operation_run"}}</button></td> + </tr> + <tr> + <td>{{ctx.Locale.Tr "admin.dashboard.git_gc_repos"}}</td> + <td class="text right"><button type="submit" class="ui primary button" name="op" value="git_gc_repos">{{svg "octicon-play"}} {{ctx.Locale.Tr "admin.dashboard.operation_run"}}</button></td> + </tr> + {{if and (not .SSH.Disabled) (not .SSH.StartBuiltinServer)}} + <tr> + <td>{{ctx.Locale.Tr "admin.dashboard.resync_all_sshkeys"}}</td> + <td class="text right"><button type="submit" class="ui primary button" name="op" value="resync_all_sshkeys">{{svg "octicon-play"}} {{ctx.Locale.Tr "admin.dashboard.operation_run"}}</button></td> + </tr> + <tr> + <td>{{ctx.Locale.Tr "admin.dashboard.resync_all_sshprincipals"}}</td> + <td class="text right"><button type="submit" class="ui primary button" name="op" value="resync_all_sshprincipals">{{svg "octicon-play" 16}} {{ctx.Locale.Tr "admin.dashboard.operation_run"}}</button></td> + </tr> + {{end}} + <tr> + <td>{{ctx.Locale.Tr "admin.dashboard.resync_all_hooks"}}</td> + <td class="text right"><button type="submit" class="ui primary button" name="op" value="resync_all_hooks">{{svg "octicon-play"}} {{ctx.Locale.Tr "admin.dashboard.operation_run"}}</button></td> + </tr> + <tr> + <td>{{ctx.Locale.Tr "admin.dashboard.reinit_missing_repos"}}</td> + <td class="text right"><button type="submit" class="ui primary button" name="op" value="reinit_missing_repos">{{svg "octicon-play"}} {{ctx.Locale.Tr "admin.dashboard.operation_run"}}</button></td> + </tr> + <tr> + <td>{{ctx.Locale.Tr "admin.dashboard.sync_external_users"}}</td> + <td class="text right"><button type="submit" class="ui primary button" name="op" value="sync_external_users">{{svg "octicon-play"}} {{ctx.Locale.Tr "admin.dashboard.operation_run"}}</button></td> + </tr> + <tr> + <td>{{ctx.Locale.Tr "admin.dashboard.repo_health_check"}}</td> + <td class="text right"><button type="submit" class="ui primary button" name="op" value="repo_health_check">{{svg "octicon-play"}} {{ctx.Locale.Tr "admin.dashboard.operation_run"}}</button></td> + </tr> + <tr> + <td>{{ctx.Locale.Tr "admin.dashboard.delete_generated_repository_avatars"}}</td> + <td class="text right"><button type="submit" class="ui primary button" name="op" value="delete_generated_repository_avatars">{{svg "octicon-play"}} {{ctx.Locale.Tr "admin.dashboard.operation_run"}}</button></td> + </tr> + <tr> + <td>{{ctx.Locale.Tr "admin.dashboard.sync_repo_branches"}}</td> + <td class="text right"><button type="submit" class="ui primary button" name="op" value="sync_repo_branches">{{svg "octicon-play"}} {{ctx.Locale.Tr "admin.dashboard.operation_run"}}</button></td> + </tr> + <tr> + <td>{{ctx.Locale.Tr "admin.dashboard.sync_repo_tags"}}</td> + <td class="text right"><button type="submit" class="ui primary button" name="op" value="sync_repo_tags">{{svg "octicon-play"}} {{ctx.Locale.Tr "admin.dashboard.operation_run"}}</button></td> + </tr> + </tbody> + </table> + </form> + </div> + + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.dashboard.system_status"}} + </h4> + {{/* TODO: make these stats work in multi-server deployments, likely needs per-server stats in DB */}} + <div class="no-loading-indicator tw-hidden"></div> + <div hx-get="{{$.Link}}/system_status" hx-swap="morph:innerHTML" hx-trigger="every 5s" hx-indicator=".no-loading-indicator" class="ui attached table segment"> + {{template "admin/system_status" .}} + </div> + </div> +{{template "admin/layout_footer" .}} diff --git a/templates/admin/emails/list.tmpl b/templates/admin/emails/list.tmpl new file mode 100644 index 0000000..b07c6fc --- /dev/null +++ b/templates/admin/emails/list.tmpl @@ -0,0 +1,116 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin user")}} + <div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.emails.email_manage_panel"}} ({{ctx.Locale.Tr "admin.total" .Total}}) + </h4> + <div class="ui attached segment"> + <div class="ui secondary filter menu tw-items-center tw-mx-0"> + <form class="ui form ignore-dirty tw-flex-1"> + {{template "shared/search/combo" dict "Value" .Keyword}} + </form> + <!-- Sort --> + <div class="ui dropdown type jump item tw-mr-0"> + <span class="text"> + {{ctx.Locale.Tr "repo.issues.filter_sort"}} + </span> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="menu"> + <a class="{{if or (eq .SortType "email") (not .SortType)}}active {{end}}item" href="?sort=email&q={{$.Keyword}}">{{ctx.Locale.Tr "admin.emails.filter_sort.email"}}</a> + <a class="{{if eq .SortType "reverseemail"}}active {{end}}item" href="?sort=reverseemail&q={{$.Keyword}}">{{ctx.Locale.Tr "admin.emails.filter_sort.email_reverse"}}</a> + <a class="{{if eq .SortType "username"}}active {{end}}item" href="?sort=username&q={{$.Keyword}}">{{ctx.Locale.Tr "admin.emails.filter_sort.name"}}</a> + <a class="{{if eq .SortType "reverseusername"}}active {{end}}item" href="?sort=reverseusername&q={{$.Keyword}}">{{ctx.Locale.Tr "admin.emails.filter_sort.name_reverse"}}</a> + </div> + </div> + </div> + </div> + <div class="ui attached table segment"> + <table class="ui very basic striped table unstackable"> + <thead> + <tr> + <th data-sortt-asc="username" data-sortt-desc="reverseusername"> + {{ctx.Locale.Tr "admin.users.name"}} + {{SortArrow "username" "reverseusername" $.SortType false}} + </th> + <th>{{ctx.Locale.Tr "admin.users.full_name"}}</th> + <th data-sortt-asc="email" data-sortt-desc="reverseemail" data-sortt-default="true"> + {{ctx.Locale.Tr "email"}} + {{SortArrow "email" "reverseemail" $.SortType true}} + </th> + <th>{{ctx.Locale.Tr "admin.emails.primary"}}</th> + <th>{{ctx.Locale.Tr "admin.emails.activated"}}</th> + <th></th> + </tr> + </thead> + <tbody> + {{range .Emails}} + <tr> + <td><a href="{{AppSubUrl}}/{{.Name | PathEscape}}">{{.Name}}</a></td> + <td class="gt-ellipsis tw-max-w-48">{{.FullName}}</td> + <td class="gt-ellipsis tw-max-w-48">{{.Email}}</td> + <td>{{if .IsPrimary}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td> + <td> + {{if .CanChange}} + <a class="link-email-action" href data-uid="{{.UID}}" + data-email="{{.Email}}" + data-primary="{{if .IsPrimary}}1{{else}}0{{end}}" + data-activate="{{if .IsActivated}}0{{else}}1{{end}}"> + {{if .IsActivated}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}} + </a> + {{else}} + {{if .IsActivated}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}} + {{end}} + </td> + <td> + <div class="tw-flex tw-gap-2"> + <a class="delete-button" href="" data-url="{{$.Link}}/delete" data-id="{{.ID}}" data-data-uid="{{.UID}}">{{svg "octicon-trash"}}</a> + </div> + </td> + </tr> + {{end}} + </tbody> + </table> + </div> + + {{template "base/paginate" .}} + + <div class="ui g-modal-confirm modal" id="change-email-modal"> + <div class="header"> + {{ctx.Locale.Tr "admin.emails.change_email_header"}} + </div> + <div class="content"> + <p class="center">{{ctx.Locale.Tr "admin.emails.change_email_text"}}</p> + + <form class="ui form" id="email-action-form" action="{{AppSubUrl}}/admin/emails/activate" method="post"> + {{$.CsrfTokenHtml}} + + <input type="hidden" id="query-sort" name="sort" value="{{.SortType}}"> + <input type="hidden" id="query-keyword" name="q" value="{{.Keyword}}"> + <input type="hidden" id="query-primary" name="is_primary" value="{{.IsPrimary}}" required> + <input type="hidden" id="query-activated" name="is_activated" value="{{.IsActivated}}" required> + + <input type="hidden" id="form-uid" name="uid" value="" required> + <input type="hidden" id="form-email" name="email" value="" required> + <input type="hidden" id="form-primary" name="primary" value="" required> + <input type="hidden" id="form-activate" name="activate" value="" required> + + <div class="center"> + {{template "base/modal_actions_confirm" .}} + </div> + </form> + </div> + </div> + + </div> + +<div class="ui g-modal-confirm delete modal"> + <div class="header"> + {{svg "octicon-trash"}} + {{ctx.Locale.Tr "admin.emails.delete"}} + </div> + <div class="content"> + {{ctx.Locale.Tr "admin.emails.delete_desc"}} + </div> + {{template "base/modal_actions_confirm" .}} +</div> + +{{template "admin/layout_footer" .}} diff --git a/templates/admin/hook_new.tmpl b/templates/admin/hook_new.tmpl new file mode 100644 index 0000000..37dcc49 --- /dev/null +++ b/templates/admin/hook_new.tmpl @@ -0,0 +1,13 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin settings new webhook")}} + <div class="admin-setting-content"> + {{$CustomHeaderTitle := ctx.Locale.Tr "admin.defaulthooks.update_webhook"}} + {{if .PageIsAdminDefaultHooksNew}} + {{$CustomHeaderTitle = ctx.Locale.Tr "admin.defaulthooks.add_webhook"}} + {{else if .PageIsAdminSystemHooksNew}} + {{$CustomHeaderTitle = ctx.Locale.Tr "admin.systemhooks.add_webhook"}} + {{else if .Webhook.IsSystemWebhook}} + {{$CustomHeaderTitle = ctx.Locale.Tr "admin.systemhooks.update_webhook"}} + {{end}} + {{template "webhook/new" (dict "ctxData" . "CustomHeaderTitle" $CustomHeaderTitle)}} + </div> +{{template "admin/layout_footer" .}} diff --git a/templates/admin/hooks.tmpl b/templates/admin/hooks.tmpl new file mode 100644 index 0000000..c77d27d --- /dev/null +++ b/templates/admin/hooks.tmpl @@ -0,0 +1,9 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin hooks")}} + <div class="admin-setting-content"> + + {{template "repo/settings/webhook/base_list" .SystemWebhooks}} + {{template "repo/settings/webhook/base_list" .DefaultWebhooks}} + + {{template "repo/settings/webhook/delete_modal" .}} + </div> +{{template "admin/layout_footer" .}} diff --git a/templates/admin/layout_footer.tmpl b/templates/admin/layout_footer.tmpl new file mode 100644 index 0000000..8d6e564 --- /dev/null +++ b/templates/admin/layout_footer.tmpl @@ -0,0 +1,11 @@ +{{if false}}{{/* to make html structure "likely" complete to prevent IDE warnings */}} +<div class="page-content"> + <div class="admin-layout-right"> + <div> + {{/* block: admin-setting-content */}} +{{end}} + + </div> + </div> +</div> +{{template "base/footer" .}} diff --git a/templates/admin/layout_head.tmpl b/templates/admin/layout_head.tmpl new file mode 100644 index 0000000..8ba47f2 --- /dev/null +++ b/templates/admin/layout_head.tmpl @@ -0,0 +1,13 @@ +{{template "base/head" .ctxData}} +<div role="main" aria-label="{{.ctxData.Title}}" class="page-content {{.pageClass}}"> + <div class="ui container flex-container"> + {{template "admin/navbar" .ctxData}} + <div class="flex-container-main"> + {{template "base/alert" .ctxData}} + {{/* block: admin-setting-content */}} + +{{if false}}{{/* to make html structure "likely" complete to prevent IDE warnings */}} + </div> + </div> +</div> +{{end}} diff --git a/templates/admin/navbar.tmpl b/templates/admin/navbar.tmpl new file mode 100644 index 0000000..1ec703b --- /dev/null +++ b/templates/admin/navbar.tmpl @@ -0,0 +1,112 @@ +<div class="flex-container-nav"> + <div class="ui fluid vertical menu"> + <div class="header item">{{ctx.Locale.Tr "admin.settings"}}</div> + <a class="{{if .PageIsAdminDashboard}}active {{end}}item" href="{{AppSubUrl}}/admin"> + {{ctx.Locale.Tr "admin.dashboard"}} + </a> + {{if .DatabaseType.IsMySQL}} + <a class="{{if .PageIsAdminSelfCheck}}active {{end}}item" href="{{AppSubUrl}}/admin/self_check"> + {{ctx.Locale.Tr "admin.self_check"}} + </a> + {{end}} + <details class="item toggleable-item" {{if or .PageIsAdminUsers .PageIsAdminEmails .PageIsAdminOrganizations .PageIsAdminAuthentications}}open{{end}}> + <summary>{{ctx.Locale.Tr "admin.identity_access"}}</summary> + <div class="menu"> + <a class="{{if .PageIsAdminAuthentications}}active {{end}}item" href="{{AppSubUrl}}/admin/auths"> + {{ctx.Locale.Tr "admin.authentication"}} + </a> + <a class="{{if .PageIsAdminOrganizations}}active {{end}}item" href="{{AppSubUrl}}/admin/orgs"> + {{ctx.Locale.Tr "admin.organizations"}} + </a> + <a class="{{if .PageIsAdminUsers}}active {{end}}item" href="{{AppSubUrl}}/admin/users"> + {{ctx.Locale.Tr "admin.users"}} + </a> + <a class="{{if .PageIsAdminEmails}}active {{end}}item" href="{{AppSubUrl}}/admin/emails"> + {{ctx.Locale.Tr "admin.emails"}} + </a> + </div> + </details> + <details class="item toggleable-item" {{if or .PageIsAdminRepositories (and .EnablePackages .PageIsAdminPackages)}}open{{end}}> + <summary>{{ctx.Locale.Tr "admin.assets"}}</summary> + <div class="menu"> + {{if .EnablePackages}} + <a class="{{if .PageIsAdminPackages}}active {{end}}item" href="{{AppSubUrl}}/admin/packages"> + {{ctx.Locale.Tr "packages.title"}} + </a> + {{end}} + <a class="{{if .PageIsAdminRepositories}}active {{end}}item" href="{{AppSubUrl}}/admin/repos"> + {{ctx.Locale.Tr "admin.repositories"}} + </a> + </div> + </details> + <!-- Webhooks and OAuth can be both disabled here, so add this if statement to display different ui --> + {{if and (not DisableWebhooks) .EnableOAuth2}} + <details class="item toggleable-item" {{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks .PageIsAdminApplications}}open{{end}}> + <summary>{{ctx.Locale.Tr "admin.integrations"}}</summary> + <div class="menu"> + <a class="{{if .PageIsAdminApplications}}active {{end}}item" href="{{AppSubUrl}}/admin/applications"> + {{ctx.Locale.Tr "settings.applications"}} + </a> + <a class="{{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks}}active {{end}}item" href="{{AppSubUrl}}/admin/hooks"> + {{ctx.Locale.Tr "admin.hooks"}} + </a> + </div> + </details> + {{else}} + {{if not DisableWebhooks}} + <a class="{{if or .PageIsAdminDefaultHooks .PageIsAdminSystemHooks}}active {{end}}item" href="{{AppSubUrl}}/admin/hooks"> + {{ctx.Locale.Tr "admin.hooks"}} + </a> + {{end}} + {{if .EnableOAuth2}} + <a class="{{if .PageIsAdminApplications}}active {{end}}item" href="{{AppSubUrl}}/admin/applications"> + {{ctx.Locale.Tr "settings.applications"}} + </a> + {{end}} + {{end}} + {{if .EnableActions}} + <details class="item toggleable-item" {{if or .PageIsSharedSettingsRunners .PageIsSharedSettingsVariables}}open{{end}}> + <summary>{{ctx.Locale.Tr "actions.actions"}}</summary> + <div class="menu"> + <a class="{{if .PageIsSharedSettingsRunners}}active {{end}}item" href="{{AppSubUrl}}/admin/actions/runners"> + {{ctx.Locale.Tr "actions.runners"}} + </a> + <a class="{{if .PageIsSharedSettingsVariables}}active {{end}}item" href="{{AppSubUrl}}/admin/actions/variables"> + {{ctx.Locale.Tr "actions.variables"}} + </a> + </div> + </details> + {{end}} + <details class="item toggleable-item" {{if or .PageIsAdminConfig}}open{{end}}> + <summary>{{ctx.Locale.Tr "admin.config"}}</summary> + <div class="menu"> + <a class="{{if .PageIsAdminConfigSummary}}active {{end}}item" href="{{AppSubUrl}}/admin/config"> + {{ctx.Locale.Tr "admin.config_summary"}} + </a> + <a class="{{if .PageIsAdminConfigSettings}}active {{end}}item" href="{{AppSubUrl}}/admin/config/settings"> + {{ctx.Locale.Tr "admin.config_settings"}} + </a> + </div> + </details> + <a class="{{if .PageIsAdminNotices}}active {{end}}item" href="{{AppSubUrl}}/admin/notices"> + {{ctx.Locale.Tr "admin.notices"}} + </a> + <details class="item toggleable-item" {{if or .PageIsAdminMonitorStats .PageIsAdminMonitorCron .PageIsAdminMonitorQueue .PageIsAdminMonitorStacktrace}}open{{end}}> + <summary>{{ctx.Locale.Tr "admin.monitor"}}</summary> + <div class="menu"> + <a class="{{if .PageIsAdminMonitorStats}}active {{end}}item" href="{{AppSubUrl}}/admin/monitor/stats"> + {{ctx.Locale.Tr "admin.monitor.stats"}} + </a> + <a class="{{if .PageIsAdminMonitorCron}}active {{end}}item" href="{{AppSubUrl}}/admin/monitor/cron"> + {{ctx.Locale.Tr "admin.monitor.cron"}} + </a> + <a class="{{if .PageIsAdminMonitorQueue}}active {{end}}item" href="{{AppSubUrl}}/admin/monitor/queue"> + {{ctx.Locale.Tr "admin.monitor.queues"}} + </a> + <a class="{{if .PageIsAdminMonitorStacktrace}}active {{end}}item" href="{{AppSubUrl}}/admin/monitor/stacktrace"> + {{ctx.Locale.Tr "admin.monitor.stacktrace"}} + </a> + </div> + </details> + </div> +</div> diff --git a/templates/admin/notice.tmpl b/templates/admin/notice.tmpl new file mode 100644 index 0000000..33d8a2f --- /dev/null +++ b/templates/admin/notice.tmpl @@ -0,0 +1,68 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin notice")}} + <div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.notices.system_notice_list"}} ({{ctx.Locale.Tr "admin.total" .Total}}) + </h4> + <table class="ui attached segment select selectable striped table unstackable g-table-auto-ellipsis"> + <thead> + <tr> + <th></th> + <th>ID</th> + <th>{{ctx.Locale.Tr "admin.notices.type"}}</th> + <th>{{ctx.Locale.Tr "admin.notices.desc"}}</th> + <th>{{ctx.Locale.Tr "admin.users.created"}}</th> + <th>{{ctx.Locale.Tr "admin.notices.op"}}</th> + </tr> + </thead> + <tbody> + {{range .Notices}} + <tr> + <td><div class="ui checkbox tw-flex" data-id="{{.ID}}"><input type="checkbox"></div></td> + <td>{{.ID}}</td> + <td>{{ctx.Locale.Tr .TrStr}}</td> + <td class="view-detail auto-ellipsis tw-w-4/5"><span class="notice-description">{{.Description}}</span></td> + <td nowrap>{{DateTime "short" .CreatedUnix}}</td> + <td class="view-detail"><a href="#">{{svg "octicon-note" 16}}</a></td> + </tr> + {{end}} + </tbody> + {{if .Notices}} + <tfoot> + <tr> + <th></th> + <th colspan="5"> + <form class="tw-float-right" method="post" action="{{AppSubUrl}}/admin/notices/empty"> + {{.CsrfTokenHtml}} + <button type="submit" class="ui red small button">{{ctx.Locale.Tr "admin.notices.delete_all"}}</button> + </form> + <div class="ui floating upward dropdown small button">{{/* TODO: Make this dropdown accessible */}} + <span class="text">{{ctx.Locale.Tr "admin.notices.operations"}}</span> + <div class="menu"> + <div class="item select action" data-action="select-all"> + {{ctx.Locale.Tr "admin.notices.select_all"}} + </div> + <div class="item select action" data-action="deselect-all"> + {{ctx.Locale.Tr "admin.notices.deselect_all"}} + </div> + <div class="item select action" data-action="inverse"> + {{ctx.Locale.Tr "admin.notices.inverse_selection"}} + </div> + </div> + </div> + <button class="ui small teal button" id="delete-selection" data-link="{{.Link}}/delete" data-redirect="?page={{.Page.Paginater.Current}}"> + <span class="text">{{ctx.Locale.Tr "admin.notices.delete_selected"}}</span> + </button> + </th> + </tr> + </tfoot> + {{end}} + </table> + {{template "base/paginate" .}} + </div> + +<div class="ui modal admin" id="detail-modal"> + <div class="header">{{ctx.Locale.Tr "admin.notices.view_detail_header"}}</div> + <div class="content"><pre></pre></div> +</div> + +{{template "admin/layout_footer" .}} diff --git a/templates/admin/org/list.tmpl b/templates/admin/org/list.tmpl new file mode 100644 index 0000000..987ceab --- /dev/null +++ b/templates/admin/org/list.tmpl @@ -0,0 +1,76 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin user")}} + <div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.orgs.org_manage_panel"}} ({{ctx.Locale.Tr "admin.total" .Total}}) + <div class="ui right"> + <a class="ui primary tiny button" href="{{AppSubUrl}}/org/create">{{ctx.Locale.Tr "admin.orgs.new_orga"}}</a> + </div> + </h4> + <div class="ui attached segment"> + <div class="ui secondary filter menu tw-items-center tw-mx-0"> + <form class="ui form ignore-dirty tw-flex-1"> + {{template "shared/search/combo" dict "Value" .Keyword "Placeholder" (ctx.Locale.Tr "search.org_kind")}} + </form> + <!-- Sort --> + <div class="ui dropdown type jump item tw-mr-0"> + <span class="text"> + {{ctx.Locale.Tr "repo.issues.filter_sort"}} + </span> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="menu"> + <a class="{{if or (eq .SortType "oldest") (not .SortType)}}active {{end}}item" href="?sort=oldest&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.oldest"}}</a> + <a class="{{if eq .SortType "newest"}}active {{end}}item" href="?sort=newest&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.latest"}}</a> + <a class="{{if eq .SortType "alphabetically"}}active {{end}}item" href="?sort=alphabetically&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.label.filter_sort.alphabetically"}}</a> + <a class="{{if eq .SortType "reversealphabetically"}}active {{end}}item" href="?sort=reversealphabetically&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a> + <a class="{{if eq .SortType "recentupdate"}}active {{end}}item" href="?sort=recentupdate&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.recentupdate"}}</a> + <a class="{{if eq .SortType "leastupdate"}}active {{end}}item" href="?sort=leastupdate&q={{$.Keyword}}">{{ctx.Locale.Tr "repo.issues.filter_sort.leastupdate"}}</a> + </div> + </div> + </div> + </div> + <div class="ui attached table segment"> + <table class="ui very basic striped table unstackable"> + <thead> + <tr> + <th data-sortt-asc="oldest" data-sortt-desc="newest">ID{{SortArrow "oldest" "newest" $.SortType false}}</th> + <th data-sortt-asc="alphabetically" data-sortt-desc="reversealphabetically" data-sortt-default="true"> + {{ctx.Locale.Tr "admin.orgs.name"}} + {{SortArrow "alphabetically" "reversealphabetically" $.SortType true}} + </th> + <th>{{ctx.Locale.Tr "admin.orgs.teams"}}</th> + <th>{{ctx.Locale.Tr "admin.orgs.members"}}</th> + <th>{{ctx.Locale.Tr "admin.users.repos"}}</th> + <th data-sortt-asc="recentupdate" data-sortt-desc="leastupdate"> + {{ctx.Locale.Tr "admin.users.created"}} + {{SortArrow "recentupdate" "leastupdate" $.SortType false}} + </th> + <th></th> + </tr> + </thead> + <tbody> + {{range .Users}} + <tr> + <td>{{.ID}}</td> + <td> + <a href="{{.HomeLink}}">{{.Name}}</a> + {{if .Visibility.IsPrivate}} + <span class="text gold">{{svg "octicon-lock"}}</span> + {{end}} + {{if eq .Type 3}}{{/* Reserved organization */}} + <span class="ui mini label">{{ctx.Locale.Tr "admin.users.reserved"}}</span> + {{end}} + </td> + <td>{{.NumTeams}}</td> + <td>{{.NumMembers}}</td> + <td>{{.NumRepos}}</td> + <td>{{DateTime "short" .CreatedUnix}}</td> + <td><a href="{{.OrganisationLink}}/settings" data-tooltip-content="{{ctx.Locale.Tr "edit"}}">{{svg "octicon-pencil"}}</a></td> + </tr> + {{end}} + </tbody> + </table> + </div> + + {{template "base/paginate" .}} + </div> +{{template "admin/layout_footer" .}} diff --git a/templates/admin/packages/list.tmpl b/templates/admin/packages/list.tmpl new file mode 100644 index 0000000..4ff49b8 --- /dev/null +++ b/templates/admin/packages/list.tmpl @@ -0,0 +1,96 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin user")}} + <div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.packages.package_manage_panel"}} ({{ctx.Locale.Tr "admin.total" .TotalCount}}, + {{ctx.Locale.Tr "admin.packages.total_size" (ctx.Locale.TrSize .TotalBlobSize)}}, + {{ctx.Locale.Tr "admin.packages.unreferenced_size" (ctx.Locale.TrSize .TotalUnreferencedBlobSize)}}) + <div class="ui right"> + <form method="post" action="{{AppSubUrl}}/admin/packages/cleanup"> + {{.CsrfTokenHtml}} + <button class="ui primary tiny button">{{ctx.Locale.Tr "admin.packages.cleanup"}}</button> + </form> + </div> + </h4> + <div class="ui attached segment"> + <form class="ui form ignore-dirty"> + <div class="ui small fluid action input"> + {{template "shared/search/input" dict "Value" .Query}} + <select class="ui small dropdown" name="type"> + <option value="">{{ctx.Locale.Tr "packages.filter.type"}}</option> + <option value="all">{{ctx.Locale.Tr "packages.filter.type.all"}}</option> + {{range $type := .AvailableTypes}} + <option{{if eq $.PackageType $type}} selected="selected"{{end}} value="{{$type}}">{{$type.Name}}</option> + {{end}} + </select> + {{template "shared/search/button"}} + </div> + </form> + </div> + <div class="ui attached table segment"> + <table class="ui very basic striped table unstackable"> + <thead> + <tr> + <th>ID</th> + <th>{{ctx.Locale.Tr "admin.packages.owner"}}</th> + <th>{{ctx.Locale.Tr "admin.packages.type"}}</th> + <th data-sortt-asc="name_asc" data-sortt-desc="name_desc"> + {{ctx.Locale.Tr "admin.packages.name"}} + {{SortArrow "name_asc" "name_desc" .SortType false}} + </th> + <th data-sortt-asc="version_desc" data-sortt-desc="version_asc"> + {{ctx.Locale.Tr "admin.packages.version"}} + {{SortArrow "version_desc" "version_asc" .SortType false}} + </th> + <th>{{ctx.Locale.Tr "admin.packages.creator"}}</th> + <th>{{ctx.Locale.Tr "admin.packages.repository"}}</th> + <th>{{ctx.Locale.Tr "admin.packages.size"}}</th> + <th data-sortt-asc="created_asc" data-sortt-desc="created_desc"> + {{ctx.Locale.Tr "admin.packages.published"}} + {{SortArrow "created_asc" "created_desc" .SortType true}} + </th> + <th>{{ctx.Locale.Tr "admin.notices.op"}}</th> + </tr> + </thead> + <tbody> + {{range .PackageDescriptors}} + <tr> + <td>{{.Version.ID}}</td> + <td> + <a href="{{.Owner.HomeLink}}">{{.Owner.Name}}</a> + {{if .Owner.Visibility.IsPrivate}} + <span class="text gold">{{svg "octicon-lock"}}</span> + {{end}} + </td> + <td>{{.Package.Type.Name}}</td> + <td class="gt-ellipsis tw-max-w-48">{{.Package.Name}}</td> + <td class="gt-ellipsis tw-max-w-48"><a href="{{.VersionWebLink}}">{{.Version.Version}}</a></td> + <td><a href="{{.Creator.HomeLink}}">{{.Creator.Name}}</a></td> + <td> + {{if .Repository}} + <a href="{{.Repository.Link}}">{{.Repository.Name}}</a> + {{end}} + </td> + <td>{{ctx.Locale.TrSize .CalculateBlobSize}}</td> + <td>{{DateTime "short" .Version.CreatedUnix}}</td> + <td><a class="delete-button" href="" data-url="{{$.Link}}/delete?page={{$.Page.Paginater.Current}}&sort={{$.SortType}}" data-id="{{.Version.ID}}" data-name="{{.Package.Name}}" data-data-version="{{.Version.Version}}">{{svg "octicon-trash"}}</a></td> + </tr> + {{end}} + </tbody> + </table> + </div> + + {{template "base/paginate" .}} + </div> + +<div class="ui g-modal-confirm delete modal"> + <div class="header"> + {{svg "octicon-trash"}} + {{ctx.Locale.Tr "packages.settings.delete"}} + </div> + <div class="content"> + {{ctx.Locale.Tr "packages.settings.delete.notice" (`<span class="name"></span>`|SafeHTML) (`<span class="dataVersion"></span>`|SafeHTML)}} + </div> + {{template "base/modal_actions_confirm" .}} +</div> + +{{template "admin/layout_footer" .}} diff --git a/templates/admin/queue.tmpl b/templates/admin/queue.tmpl new file mode 100644 index 0000000..1be35cf --- /dev/null +++ b/templates/admin/queue.tmpl @@ -0,0 +1,36 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin monitor")}} +<div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.monitor.queues"}} + </h4> + <div class="ui attached table segment"> + <table class="ui very basic striped table unstackable"> + <thead> + <tr> + <th>{{ctx.Locale.Tr "admin.monitor.queue.name"}}</th> + <th>{{ctx.Locale.Tr "admin.monitor.queue.type"}}</th> + <th>{{ctx.Locale.Tr "admin.monitor.queue.exemplar"}}</th> + <th>{{ctx.Locale.Tr "admin.monitor.queue.numberworkers"}}</th> + <th>{{ctx.Locale.Tr "admin.monitor.queue.activeworkers"}}</th> + <th>{{ctx.Locale.Tr "admin.monitor.queue.numberinqueue"}}</th> + <th></th> + </tr> + </thead> + <tbody> + {{range $qid, $q := .Queues}} + <tr> + <td>{{$q.GetName}}</td> + <td>{{$q.GetType}}</td> + <td>{{$q.GetItemTypeName}}</td> + <td>{{$q.GetWorkerNumber}}</td> + <td>{{$q.GetWorkerActiveNumber}}</td> + <td>{{$sum := $q.GetQueueItemNumber}}{{if lt $sum 0}}-{{else}}{{$sum}}{{end}}</td> + <td><a href="{{$.Link}}/{{$qid}}" class="button">{{ctx.Locale.Tr "admin.monitor.queue.review_add"}}</a></td> + </tr> + {{end}} + </tbody> + </table> + </div> +</div> +{{template "admin/layout_footer" .}} + diff --git a/templates/admin/queue_manage.tmpl b/templates/admin/queue_manage.tmpl new file mode 100644 index 0000000..dc0196f --- /dev/null +++ b/templates/admin/queue_manage.tmpl @@ -0,0 +1,61 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin monitor")}} + <div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.monitor.queue" .Queue.GetName}} + </h4> + <div class="ui attached table segment"> + <table class="ui very basic striped table"> + <thead> + <tr> + <th>{{ctx.Locale.Tr "admin.monitor.queue.name"}}</th> + <th>{{ctx.Locale.Tr "admin.monitor.queue.type"}}</th> + <th>{{ctx.Locale.Tr "admin.monitor.queue.exemplar"}}</th> + <th>{{ctx.Locale.Tr "admin.monitor.queue.numberworkers"}}</th> + <th>{{ctx.Locale.Tr "admin.monitor.queue.activeworkers"}}</th> + <th>{{ctx.Locale.Tr "admin.monitor.queue.maxnumberworkers"}}</th> + <th>{{ctx.Locale.Tr "admin.monitor.queue.numberinqueue"}}</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{.Queue.GetName}}</td> + <td>{{.Queue.GetType}}</td> + <td>{{.Queue.GetItemTypeName}}</td> + <td>{{.Queue.GetWorkerNumber}}</td> + <td>{{.Queue.GetWorkerActiveNumber}}</td> + <td>{{.Queue.GetWorkerMaxNumber}}</td> + <td> + {{$sum := .Queue.GetQueueItemNumber}} + {{if lt $sum 0}} + - + {{else}} + {{$sum}} + <form action="{{$.Link}}/remove-all-items" method="post" class="tw-inline-block tw-ml-4"> + {{$.CsrfTokenHtml}} + <button class="ui tiny basic red button">{{ctx.Locale.Tr "admin.monitor.queue.settings.remove_all_items"}}</button> + </form> + {{end}} + </td> + </tr> + </tbody> + </table> + </div> + + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.monitor.queue.settings.title"}} + </h4> + <div class="ui attached segment"> + <p>{{ctx.Locale.Tr "admin.monitor.queue.settings.desc"}}</p> + <form method="post" action="{{.Link}}/set"> + {{$.CsrfTokenHtml}} + <div class="ui form"> + <div class="inline field"> + <label for="max-number">{{ctx.Locale.Tr "admin.monitor.queue.settings.maxnumberworkers"}}</label> + <input name="max-number" type="text" placeholder="{{ctx.Locale.Tr "admin.monitor.queue.settings.maxnumberworkers.placeholder" .Queue.GetWorkerMaxNumber}}"> + </div> + <button class="ui submit button">{{ctx.Locale.Tr "admin.monitor.queue.settings.submit"}}</button> + </div> + </form> + </div> + </div> +{{template "admin/layout_footer" .}} diff --git a/templates/admin/repo/list.tmpl b/templates/admin/repo/list.tmpl new file mode 100644 index 0000000..1ea6183 --- /dev/null +++ b/templates/admin/repo/list.tmpl @@ -0,0 +1,110 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin")}} + <div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.repos.repo_manage_panel"}} ({{ctx.Locale.Tr "admin.total" .Total}}) + <div class="ui right"> + <a class="ui primary tiny button" href="{{AppSubUrl}}/admin/repos/unadopted">{{ctx.Locale.Tr "admin.repos.unadopted"}}</a> + </div> + </h4> + <div class="ui attached segment"> + {{template "shared/repo_search" .}} + </div> + <div class="ui attached table segment"> + <table class="ui very basic striped table unstackable"> + <thead> + <tr> + <th data-sortt-asc="oldest" data-sortt-desc="newest">ID{{SortArrow "oldest" "newest" $.SortType false}}</th> + <th>{{ctx.Locale.Tr "admin.repos.owner"}}</th> + <th data-sortt-asc="alphabetically" data-sortt-desc="reversealphabetically"> + {{ctx.Locale.Tr "admin.repos.name"}} + {{SortArrow "alphabetically" "reversealphabetically" $.SortType false}} + </th> + <th>{{ctx.Locale.Tr "repo.watchers"}}</th> + <th data-sortt-asc="moststars" data-sortt-desc="feweststars"> + {{ctx.Locale.Tr "repo.stars"}} + {{SortArrow "moststars" "feweststars" $.SortType false}} + </th> + <th data-sortt-asc="mostforks" data-sortt-desc="fewestforks"> + {{ctx.Locale.Tr "repo.forks"}} + {{SortArrow "mostforks" "fewestforks" $.SortType false}} + </th> + <th>{{ctx.Locale.Tr "admin.repos.issues"}}</th> + <th data-sortt-asc="gitsize" data-sortt-desc="reversegitsize"> + {{ctx.Locale.Tr "admin.repos.size"}} + {{SortArrow "gitsize" "reversegitsize" $.SortType false}} + </th> + <th data-sortt-asc="lfssize" data-sortt-desc="reverselfssize"> + {{ctx.Locale.Tr "admin.repos.lfs_size"}} + {{SortArrow "lfssize" "reverselfssize" $.SortType false}} + </th> + <th>{{ctx.Locale.Tr "admin.auths.updated"}}</th> + <th>{{ctx.Locale.Tr "admin.users.created"}}</th> + <th>{{ctx.Locale.Tr "admin.notices.op"}}</th> + </tr> + </thead> + <tbody> + {{range .Repos}} + <tr> + <td>{{.ID}}</td> + <td> + <a class="tw-break-anywhere" href="{{.Owner.HomeLink}}">{{.Owner.Name}}</a> + {{if .Owner.Visibility.IsPrivate}} + <span class="text gold">{{svg "octicon-lock"}}</span> + {{end}} + </td> + <td> + <a class="tw-break-anywhere" href="{{.Link}}">{{.Name}}</a> + {{if .IsArchived}} + <span class="ui basic label">{{ctx.Locale.Tr "repo.desc.archived"}}</span> + {{end}} + {{if .IsPrivate}} + <span class="ui basic label">{{ctx.Locale.Tr "repo.desc.private"}}</span> + {{else}} + {{if .Owner.Visibility.IsPrivate}} + <span class="ui basic label">{{ctx.Locale.Tr "repo.desc.internal"}}</span> + {{end}} + {{end}} + {{if .IsTemplate}} + <span class="ui basic label">{{ctx.Locale.Tr "repo.desc.template"}}</span> + {{end}} + {{if eq .ObjectFormatName "sha256"}} + <span class="ui basic label">{{ctx.Locale.Tr "repo.desc.sha256"}}</span> + {{end}} + {{if .IsMirror}} + {{svg "octicon-mirror"}} + {{else if .IsFork}} + {{svg "octicon-repo-forked"}} + {{end}} + </td> + <td>{{.NumWatches}}</td> + <td>{{.NumStars}}</td> + <td>{{.NumForks}}</td> + <td>{{.NumIssues}}</td> + <td>{{ctx.Locale.TrSize .GitSize}}</td> + <td>{{ctx.Locale.TrSize .LFSSize}}</td> + <td>{{DateTime "short" .UpdatedUnix}}</td> + <td>{{DateTime "short" .CreatedUnix}}</td> + <td><a class="delete-button" href="" data-url="{{$.Link}}/delete?page={{$.Page.Paginater.Current}}&sort={{$.SortType}}" data-id="{{.ID}}" data-name="{{.Name}}">{{svg "octicon-trash"}}</a></td> + </tr> + {{end}} + </tbody> + </table> + </div> + + {{template "base/paginate" .}} + </div> + +<div class="ui g-modal-confirm delete modal"> + <div class="header"> + {{svg "octicon-trash"}} + {{ctx.Locale.Tr "repo.settings.delete"}} + </div> + <div class="content"> + <p>{{ctx.Locale.Tr "repo.settings.delete_desc"}}</p> + {{ctx.Locale.Tr "repo.settings.delete_notices_2" (`<span class="name"></span>`|SafeHTML)}}<br> + {{ctx.Locale.Tr "repo.settings.delete_notices_fork_1"}}<br> + </div> + {{template "base/modal_actions_confirm" .}} +</div> + +{{template "admin/layout_footer" .}} diff --git a/templates/admin/repo/unadopted.tmpl b/templates/admin/repo/unadopted.tmpl new file mode 100644 index 0000000..a33cb43 --- /dev/null +++ b/templates/admin/repo/unadopted.tmpl @@ -0,0 +1,75 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin")}} + <div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.repos.unadopted"}} + <div class="ui right"> + <a class="ui primary tiny button" href="{{AppSubUrl}}/admin/repos">{{ctx.Locale.Tr "admin.repos.repo_manage_panel"}}</a> + </div> + </h4> + <div class="ui attached segment"> + <form class="ui form ignore-dirty"> + <div class="ui small fluid action input"> + <input name="search" value="true" type="hidden"> + <input name="q" value="{{.Keyword}}" placeholder="{{ctx.Locale.Tr "repo.adopt_search"}}" autofocus> + {{template "shared/search/button"}} + </div> + </form> + </div> + {{if .search}} + <div class="ui attached segment settings"> + {{if .Dirs}} + <div class="ui aligned divided list"> + {{range $dirI, $dir := .Dirs}} + <div class="item tw-flex tw-items-center"> + <span class="tw-flex-1"> {{svg "octicon-file-directory-fill"}} {{$dir}}</span> + <div> + <button class="ui button primary show-modal tw-p-2" data-modal="#adopt-unadopted-modal-{{$dirI}}">{{svg "octicon-plus"}} {{ctx.Locale.Tr "repo.adopt_preexisting_label"}}</button> + <div class="ui g-modal-confirm modal" id="adopt-unadopted-modal-{{$dirI}}"> + <div class="header"> + <span class="label">{{ctx.Locale.Tr "repo.adopt_preexisting"}}</span> + </div> + <div class="content"> + <p>{{ctx.Locale.Tr "repo.adopt_preexisting_content" $dir}}</p> + </div> + <form class="ui form" method="post" action="{{AppSubUrl}}/admin/repos/unadopted"> + {{$.CsrfTokenHtml}} + <input type="hidden" name="id" value="{{$dir}}"> + <input type="hidden" name="action" value="adopt"> + <input type="hidden" name="q" value="{{$.Keyword}}"> + <input type="hidden" name="page" value="{{$.CurrentPage}}"> + {{template "base/modal_actions_confirm"}} + </form> + </div> + <button class="ui button red show-modal tw-p-2" data-modal="#delete-unadopted-modal-{{$dirI}}">{{svg "octicon-x"}} {{ctx.Locale.Tr "repo.delete_preexisting_label"}}</button> + <div class="ui g-modal-confirm modal" id="delete-unadopted-modal-{{$dirI}}"> + <div class="header"> + <span class="label">{{ctx.Locale.Tr "repo.delete_preexisting"}}</span> + </div> + <div class="content"> + <p>{{ctx.Locale.Tr "repo.delete_preexisting_content" $dir}}</p> + </div> + <form class="ui form" method="post" action="{{AppSubUrl}}/admin/repos/unadopted"> + {{$.CsrfTokenHtml}} + <input type="hidden" name="id" value="{{$dir}}"> + <input type="hidden" name="action" value="delete"> + <input type="hidden" name="q" value="{{$.Keyword}}"> + <input type="hidden" name="page" value="{{$.CurrentPage}}"> + {{template "base/modal_actions_confirm" (dict "ModalButtonColors" "primary")}} + </form> + </div> + </div> + </div> + {{end}} + </div> + {{template "base/paginate" .}} + {{else}} + <div class="item"> + {{ctx.Locale.Tr "admin.repos.unadopted.no_more"}} + </div> + {{template "base/paginate" .}} + {{end}} + </div> + {{end}} + </div> + +{{template "admin/layout_footer" .}} diff --git a/templates/admin/runners/edit.tmpl b/templates/admin/runners/edit.tmpl new file mode 100644 index 0000000..1165c84 --- /dev/null +++ b/templates/admin/runners/edit.tmpl @@ -0,0 +1,5 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin runners")}} + <div class="admin-setting-content"> + {{template "shared/actions/runner_edit" .}} + </div> +{{template "admin/layout_footer" .}} diff --git a/templates/admin/self_check.tmpl b/templates/admin/self_check.tmpl new file mode 100644 index 0000000..afcd4cd --- /dev/null +++ b/templates/admin/self_check.tmpl @@ -0,0 +1,41 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin config")}} + +<div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.self_check"}} + </h4> + <div class="ui attached segment"> + {{if .DatabaseCheckHasProblems}} + {{if .DatabaseType.IsMySQL}} + <div class="tw-p-2">{{ctx.Locale.Tr "admin.self_check.database_fix_mysql"}}</div> + {{end}} + {{if .DatabaseCheckCollationMismatch}} + <div class="ui red message">{{ctx.Locale.Tr "admin.self_check.database_collation_mismatch" .DatabaseCheckResult.ExpectedCollation}}</div> + {{end}} + {{if .DatabaseCheckCollationCaseInsensitive}} + <div class="ui warning message">{{ctx.Locale.Tr "admin.self_check.database_collation_case_insensitive" .DatabaseCheckResult.DatabaseCollation}}</div> + {{end}} + {{if .DatabaseCheckInconsistentCollationColumns}} + <div class="ui red message"> + {{ctx.Locale.Tr "admin.self_check.database_inconsistent_collation_columns" .DatabaseCheckResult.DatabaseCollation}} + <ul class="tw-w-full"> + {{range .DatabaseCheckInconsistentCollationColumns}} + <li>{{.}}</li> + {{end}} + </ul> + </div> + {{end}} + {{else}} + <div class="tw-p-2">{{ctx.Locale.Tr "admin.self_check.no_problem_found"}}</div> + {{end}} + + {{if .CacheError}} + <div class="ui red message">{{ctx.Locale.Tr "admin.config.cache_test_failed" .CacheError}}</div> + {{end}} + {{if .CacheSlow}} + <div class="ui warning message">{{ctx.Locale.Tr "admin.config.cache_test_slow" .CacheSlow}}</div> + {{end}} + </div> +</div> + +{{template "admin/layout_footer" .}} diff --git a/templates/admin/stacktrace-row.tmpl b/templates/admin/stacktrace-row.tmpl new file mode 100644 index 0000000..694bf56 --- /dev/null +++ b/templates/admin/stacktrace-row.tmpl @@ -0,0 +1,66 @@ +<div class="item"> + <div class="tw-flex tw-items-center"> + <div class="icon tw-ml-2 tw-mr-2"> + {{if eq .Process.Type "request"}} + {{svg "octicon-globe" 16}} + {{else if eq .Process.Type "system"}} + {{svg "octicon-cpu" 16}} + {{else if eq .Process.Type "normal"}} + {{svg "octicon-terminal" 16}} + {{else}} + {{svg "octicon-code" 16}} + {{end}} + </div> + <div class="content tw-flex-1"> + <div class="header">{{.Process.Description}}</div> + <div class="description">{{if ne .Process.Type "none"}}{{TimeSince .Process.Start ctx.Locale}}{{end}}</div> + </div> + <div> + {{if or (eq .Process.Type "request") (eq .Process.Type "normal")}} + <a class="delete-button icon" href="" data-url="{{.root.Link}}/cancel/{{.Process.PID}}" data-id="{{.Process.PID}}" data-name="{{.Process.Description}}">{{svg "octicon-trash" 16 "text-red"}}</a> + {{end}} + </div> + </div> + {{if .Process.Stacks}} + <div class="divided list tw-ml-2"> + {{range .Process.Stacks}} + <div class="item"> + <details> + <summary> + <div class="flex-text-inline"> + <div class="header tw-ml-2"> + <span class="icon tw-mr-2">{{svg "octicon-code" 16}}</span>{{.Description}}{{if gt .Count 1}} * {{.Count}}{{end}} + </div> + <div class="description"> + {{range .Labels}} + <div class="ui label">{{.Name}}<div class="detail">{{.Value}}</div></div> + {{end}} + </div> + </div> + </summary> + <div class="list"> + {{range .Entry}} + <div class="item tw-flex tw-items-center"> + <span class="icon tw-mr-4">{{svg "octicon-dot-fill" 16}}</span> + <div class="content tw-flex-1"> + <div class="header"><code>{{.Function}}</code></div> + <div class="description"><code>{{.File}}:{{.Line}}</code></div> + </div> + </div> + {{end}} + </div> + </details> + </div> + {{end}} + </div> + {{end}} + + {{if .Process.Children}} + <div class="divided list"> + {{range .Process.Children}} + {{template "admin/stacktrace-row" dict "Process" . "root" $.root}} + {{end}} + </div> + {{end}} + +</div> diff --git a/templates/admin/stacktrace.tmpl b/templates/admin/stacktrace.tmpl new file mode 100644 index 0000000..e324570 --- /dev/null +++ b/templates/admin/stacktrace.tmpl @@ -0,0 +1,48 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin monitor")}} +<div class="admin-setting-content"> + + <div class="tw-flex tw-items-center"> + <div class="tw-flex-1"> + <div class="ui compact small menu"> + <a class="{{if eq .ShowGoroutineList "process"}}active {{end}}item" href="?show=process">{{ctx.Locale.Tr "admin.monitor.process"}}</a> + <a class="{{if eq .ShowGoroutineList "stacktrace"}}active {{end}}item" href="?show=stacktrace">{{ctx.Locale.Tr "admin.monitor.stacktrace"}}</a> + </div> + </div> + <form target="_blank" action="{{AppSubUrl}}/admin/monitor/diagnosis" class="ui form"> + <div class="ui inline field"> + <button class="ui primary small button">{{ctx.Locale.Tr "admin.monitor.download_diagnosis_report"}}</button> + <input name="seconds" size="3" maxlength="3" value="10"> {{ctx.Locale.Tr "tool.raw_seconds"}} + </div> + </form> + </div> + + <div class="divider"></div> + + <h4 class="ui top attached header"> + {{printf "%d Goroutines" .GoroutineCount}}{{/* Goroutine is non-translatable*/}} + {{- if .ProcessCount -}}, {{ctx.Locale.Tr "admin.monitor.processes_count" .ProcessCount}}{{- end -}} + </h4> + + {{if .ProcessStacks}} + <div class="ui attached segment"> + <div class="ui relaxed divided list"> + {{range .ProcessStacks}} + {{template "admin/stacktrace-row" dict "Process" . "root" $}} + {{end}} + </div> + </div> + {{end}} +</div> + +<div class="ui g-modal-confirm delete modal"> + <div class="header"> + {{ctx.Locale.Tr "admin.monitor.process.cancel"}} + </div> + <div class="content"> + <p>{{ctx.Locale.Tr "admin.monitor.process.cancel_notices" (`<span class="name"></span>`|SafeHTML)}}</p> + <p>{{ctx.Locale.Tr "admin.monitor.process.cancel_desc"}}</p> + </div> + {{template "base/modal_actions_confirm" .}} +</div> + +{{template "admin/layout_footer" .}} diff --git a/templates/admin/stats.tmpl b/templates/admin/stats.tmpl new file mode 100644 index 0000000..70f2aa7 --- /dev/null +++ b/templates/admin/stats.tmpl @@ -0,0 +1,17 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin monitor")}} +<div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.dashboard.statistic"}} + </h4> + <div class="ui attached table segment"> + <table class="ui very basic striped table unstackable"> + {{range $statsKey, $statsValue := .Stats}} + <tr> + <td width="200">{{$statsKey}}</td> + <td>{{$statsValue}}</td> + </tr> + {{end}} + </table> + </div> +</div> +{{template "admin/layout_footer" .}} diff --git a/templates/admin/system_status.tmpl b/templates/admin/system_status.tmpl new file mode 100644 index 0000000..7b5c9be --- /dev/null +++ b/templates/admin/system_status.tmpl @@ -0,0 +1,62 @@ +<dl class="admin-dl-horizontal"> + <dt>{{ctx.Locale.Tr "admin.dashboard.server_uptime"}}</dt> + <dd><relative-time format="duration" datetime="{{.SysStatus.StartTime}}">{{.SysStatus.StartTime}}</relative-time></dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.current_goroutine"}}</dt> + <dd>{{.SysStatus.NumGoroutine}}</dd> + <div class="divider"></div> + <dt>{{ctx.Locale.Tr "admin.dashboard.current_memory_usage"}}</dt> + <dd>{{.SysStatus.MemAllocated}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.total_memory_allocated"}}</dt> + <dd>{{.SysStatus.MemTotal}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.memory_obtained"}}</dt> + <dd>{{.SysStatus.MemSys}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.pointer_lookup_times"}}</dt> + <dd>{{.SysStatus.Lookups}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.memory_allocate_times"}}</dt> + <dd>{{.SysStatus.MemMallocs}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.memory_free_times"}}</dt> + <dd>{{.SysStatus.MemFrees}}</dd> + <div class="divider"></div> + <dt>{{ctx.Locale.Tr "admin.dashboard.current_heap_usage"}}</dt> + <dd>{{.SysStatus.HeapAlloc}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.heap_memory_obtained"}}</dt> + <dd>{{.SysStatus.HeapSys}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.heap_memory_idle"}}</dt> + <dd>{{.SysStatus.HeapIdle}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.heap_memory_in_use"}}</dt> + <dd>{{.SysStatus.HeapInuse}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.heap_memory_released"}}</dt> + <dd>{{.SysStatus.HeapReleased}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.heap_objects"}}</dt> + <dd>{{.SysStatus.HeapObjects}}</dd> + <div class="divider"></div> + <dt>{{ctx.Locale.Tr "admin.dashboard.bootstrap_stack_usage"}}</dt> + <dd>{{.SysStatus.StackInuse}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.stack_memory_obtained"}}</dt> + <dd>{{.SysStatus.StackSys}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.mspan_structures_usage"}}</dt> + <dd>{{.SysStatus.MSpanInuse}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.mspan_structures_obtained"}}</dt> + <dd>{{.SysStatus.MSpanSys}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.mcache_structures_usage"}}</dt> + <dd>{{.SysStatus.MCacheInuse}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.mcache_structures_obtained"}}</dt> + <dd>{{.SysStatus.MCacheSys}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.profiling_bucket_hash_table_obtained"}}</dt> + <dd>{{.SysStatus.BuckHashSys}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.gc_metadata_obtained"}}</dt> + <dd>{{.SysStatus.GCSys}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.other_system_allocation_obtained"}}</dt> + <dd>{{.SysStatus.OtherSys}}</dd> + <div class="divider"></div> + <dt>{{ctx.Locale.Tr "admin.dashboard.next_gc_recycle"}}</dt> + <dd>{{.SysStatus.NextGC}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.last_gc_time"}}</dt> + <dd><relative-time format="duration" datetime="{{.SysStatus.LastGCTime}}">{{.SysStatus.LastGCTime}}</relative-time></dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.total_gc_pause"}}</dt> + <dd>{{.SysStatus.PauseTotalNs}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.last_gc_pause"}}</dt> + <dd>{{.SysStatus.PauseNs}}</dd> + <dt>{{ctx.Locale.Tr "admin.dashboard.gc_times"}}</dt> + <dd>{{.SysStatus.NumGC}}</dd> +</dl> diff --git a/templates/admin/user/edit.tmpl b/templates/admin/user/edit.tmpl new file mode 100644 index 0000000..f5c85e9 --- /dev/null +++ b/templates/admin/user/edit.tmpl @@ -0,0 +1,242 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin edit user")}} + <div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.users.edit_account"}} + </h4> + <div class="ui attached segment"> + <form class="ui form" action="./edit" method="post"> + {{template "base/disable_form_autofill"}} + {{.CsrfTokenHtml}} + <div class="field {{if .Err_UserName}}error{{end}}"> + <label for="user_name">{{ctx.Locale.Tr "username"}}</label> + <input id="user_name" name="user_name" value="{{.User.Name}}" autofocus {{if not .User.IsLocal}}disabled{{end}} maxlength="40"> + </div> + <!-- Types and name --> + <div class="inline required field {{if .Err_LoginType}}error{{end}}"> + <label>{{ctx.Locale.Tr "admin.users.auth_source"}}</label> + <div class="ui selection type dropdown"> + <input type="hidden" id="login_type" name="login_type" value="{{.LoginSource.Type.Int}}-{{.LoginSource.ID}}" required> + <div class="text">{{ctx.Locale.Tr "admin.users.local"}}</div> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="menu"> + <div class="item" data-value="0-0">{{ctx.Locale.Tr "admin.users.local"}}</div> + {{range .Sources}} + <div class="item" data-value="{{.Type.Int}}-{{.ID}}">{{.Name}}</div> + {{end}} + </div> + </div> + </div> + + <div class="inline field {{if .Err_Visibility}}error{{end}}"> + <span class="inline required field"><label for="visibility">{{ctx.Locale.Tr "settings.visibility"}}</label></span> + <div class="ui selection type dropdown"> + {{if .User.Visibility.IsPublic}}<input type="hidden" id="visibility" name="visibility" value="0">{{end}} + {{if .User.Visibility.IsLimited}}<input type="hidden" id="visibility" name="visibility" value="1">{{end}} + {{if .User.Visibility.IsPrivate}}<input type="hidden" id="visibility" name="visibility" value="2">{{end}} + <div class="text"> + {{if .User.Visibility.IsPublic}}{{ctx.Locale.Tr "settings.visibility.public"}}{{end}} + {{if .User.Visibility.IsLimited}}{{ctx.Locale.Tr "settings.visibility.limited"}}{{end}} + {{if .User.Visibility.IsPrivate}}{{ctx.Locale.Tr "settings.visibility.private"}}{{end}} + </div> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="menu"> + {{range $mode := .AllowedUserVisibilityModes}} + {{if $mode.IsPublic}} + <div class="item" data-tooltip-content="{{ctx.Locale.Tr "settings.visibility.public_tooltip"}}" data-value="0">{{ctx.Locale.Tr "settings.visibility.public"}}</div> + {{else if $mode.IsLimited}} + <div class="item" data-tooltip-content="{{ctx.Locale.Tr "settings.visibility.limited_tooltip"}}" data-value="1">{{ctx.Locale.Tr "settings.visibility.limited"}}</div> + {{else if $mode.IsPrivate}} + <div class="item" data-tooltip-content="{{ctx.Locale.Tr "settings.visibility.private_tooltip"}}" data-value="2">{{ctx.Locale.Tr "settings.visibility.private"}}</div> + {{end}} + {{end}} + </div> + </div> + </div> + + <div class="required non-local field {{if .Err_LoginName}}error{{end}} {{if eq .User.LoginSource 0}}tw-hidden{{end}}"> + <label for="login_name">{{ctx.Locale.Tr "admin.users.auth_login_name"}}</label> + <input id="login_name" name="login_name" value="{{.User.LoginName}}" autofocus> + </div> + <div class="field {{if .Err_FullName}}error{{end}}"> + <label for="full_name">{{ctx.Locale.Tr "settings.full_name"}}</label> + <input id="full_name" name="full_name" value="{{.User.FullName}}" maxlength="100"> + </div> + <div class="field"> + <label for="pronouns">{{ctx.Locale.Tr "settings.pronouns"}}</label> + <input id="pronouns" name="pronouns" value="{{.User.Pronouns}}" maxlength="50"> + </div> + <div class="required field {{if .Err_Email}}error{{end}}"> + <label for="email">{{ctx.Locale.Tr "email"}}</label> + <input id="email" name="email" type="email" value="{{.User.Email}}" autofocus required> + </div> + <div class="local field {{if .Err_Password}}error{{end}} {{if not (or (.User.IsLocal) (.User.IsOAuth2))}}tw-hidden{{end}}"> + <label for="password">{{ctx.Locale.Tr "password"}}</label> + <input id="password" name="password" type="password" autocomplete="new-password"> + <p class="help">{{ctx.Locale.Tr "admin.users.password_helper"}}</p> + </div> + + <div class="field {{if .Err_Language}}error{{end}}"> + <label for="language">{{ctx.Locale.Tr "settings.language"}}</label> + <div class="ui selection dropdown"> + <input name="language" type="hidden" value="{{.User.Language}}"> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="text">{{range .AllLangs}}{{if eq $.User.Language .Lang}}{{.Name}}{{end}}{{end}}</div> + <div class="menu"> + {{range .AllLangs}} + <div class="item{{if eq $.User.Language .Lang}} active selected{{end}}" data-value="{{.Lang}}">{{.Name}}</div> + {{end}} + </div> + </div> + </div> + + <div class="field {{if .Err_Website}}error{{end}}"> + <label for="website">{{ctx.Locale.Tr "settings.website"}}</label> + <input id="website" name="website" type="url" value="{{.User.Website}}" placeholder="http://mydomain.com or https://mydomain.com" maxlength="255"> + </div> + <div class="field {{if .Err_Location}}error{{end}}"> + <label for="location">{{ctx.Locale.Tr "settings.location"}}</label> + <input id="location" name="location" value="{{.User.Location}}" maxlength="50"> + </div> + + <div class="divider"></div> + + <div class="inline field {{if .Err_MaxRepoCreation}}error{{end}}"> + <label for="max_repo_creation">{{ctx.Locale.Tr "admin.users.max_repo_creation"}}</label> + <input id="max_repo_creation" name="max_repo_creation" type="number" min="-1" value="{{.User.MaxRepoCreation}}"> + <p class="help">{{ctx.Locale.Tr "admin.users.max_repo_creation_desc"}}</p> + </div> + + <div class="divider"></div> + + <div class="inline field"> + <div class="ui checkbox"> + <label>{{ctx.Locale.Tr "admin.users.is_activated"}}</label> + <input name="active" type="checkbox" {{if .User.IsActive}}checked{{end}}> + </div> + <span class="help tw-block">{{ctx.Locale.Tr "admin.users.activated.description"}}</span> + </div> + <div class="inline field"> + <div class="ui checkbox"> + <label>{{ctx.Locale.Tr "admin.users.prohibit_login"}}</label> + <input name="prohibit_login" type="checkbox" {{if .User.ProhibitLogin}}checked{{end}} {{if (eq .User.ID .SignedUserID)}}disabled{{end}}> + </div> + <span class="help tw-block">{{ctx.Locale.Tr "admin.users.block.description"}}</span> + </div> + <div class="inline field"> + <div class="ui checkbox"> + <label>{{ctx.Locale.Tr "admin.users.is_admin"}}</label> + <input name="admin" type="checkbox" {{if .User.IsAdmin}}checked{{end}}> + </div> + <span class="help tw-block">{{ctx.Locale.Tr "admin.users.admin.description"}}</span> + </div> + <div class="inline field"> + <div class="ui checkbox"> + <label>{{ctx.Locale.Tr "admin.users.is_restricted"}}</label> + <input name="restricted" type="checkbox" {{if .User.IsRestricted}}checked{{end}}> + </div> + <span class="help tw-block">{{ctx.Locale.Tr "admin.users.restricted.description"}}</span> + </div> + <div class="inline field {{if DisableGitHooks}}tw-hidden{{end}}"> + <div class="ui checkbox"> + <label>{{ctx.Locale.Tr "admin.users.allow_git_hook"}}</label> + <input name="allow_git_hook" type="checkbox" {{if .User.CanEditGitHook}}checked{{end}} {{if DisableGitHooks}}disabled{{end}}> + </div> + <span class="help tw-block">{{ctx.Locale.Tr "admin.users.allow_git_hook_tooltip"}}</span> + </div> + <div class="inline field {{if or (DisableImportLocal) (.DisableMigrations)}}tw-hidden{{end}}"> + <div class="ui checkbox"> + <label>{{ctx.Locale.Tr "admin.users.allow_import_local"}}</label> + <input name="allow_import_local" type="checkbox" {{if .User.CanImportLocal}}checked{{end}} {{if DisableImportLocal}}disabled{{end}}> + </div> + <span class="help tw-block">{{ctx.Locale.Tr "admin.users.local_import.description"}}</span> + </div> + {{if not .DisableRegularOrgCreation}} + <div class="inline field"> + <div class="ui checkbox"> + <label>{{ctx.Locale.Tr "admin.users.allow_create_organization"}}</label> + <input name="allow_create_organization" type="checkbox" {{if .User.CanCreateOrganization}}checked{{end}}> + </div> + <span class="help tw-block">{{ctx.Locale.Tr "admin.users.organization_creation.description"}}</span> + </div> + {{end}} + + {{if .TwoFactorEnabled}} + <div class="divider"></div> + <div class="inline field"> + <div class="ui checkbox"> + <label><strong>{{ctx.Locale.Tr "admin.users.reset_2fa"}}</strong></label> + <input name="reset_2fa" type="checkbox"> + </div> + </div> + {{end}} + + <div class="divider"></div> + + <div class="field"> + <button class="ui primary button">{{ctx.Locale.Tr "admin.users.update_profile"}}</button> + <button class="ui red button show-modal" data-modal="#delete-user-modal">{{ctx.Locale.Tr "admin.users.delete_account"}}</button> + </div> + </form> + </div> + + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "settings.avatar"}} + </h4> + <div class="ui attached segment"> + <form class="ui form" action="./avatar" method="post" enctype="multipart/form-data"> + {{.CsrfTokenHtml}} + {{if not .DisableGravatar}} + <div class="inline field"> + <div class="ui radio checkbox"> + <input name="source" value="lookup" type="radio" {{if not .User.UseCustomAvatar}}checked{{end}}> + <label>{{ctx.Locale.Tr "settings.lookup_avatar_by_mail"}}</label> + </div> + </div> + <div class="field tw-pl-4 {{if .Err_Gravatar}}error{{end}}"> + <label for="gravatar">Avatar {{ctx.Locale.Tr "email"}}</label> + <input id="gravatar" name="gravatar" value="{{.User.AvatarEmail}}"> + </div> + {{end}} + + <div class="inline field"> + <div class="ui radio checkbox"> + <input name="source" value="local" type="radio" {{if .User.UseCustomAvatar}}checked{{end}}> + <label>{{ctx.Locale.Tr "settings.enable_custom_avatar"}}</label> + </div> + </div> + + <div class="inline field tw-pl-4"> + <label for="avatar">{{ctx.Locale.Tr "settings.choose_new_avatar"}}</label> + <input name="avatar" type="file" accept="image/png,image/jpeg,image/gif,image/webp"> + </div> + + <div class="field"> + <button class="ui primary button">{{ctx.Locale.Tr "settings.update_avatar"}}</button> + <button class="ui red button link-action" data-url="./avatar/delete">{{ctx.Locale.Tr "settings.delete_current_avatar"}}</button> + </div> + </form> + </div> + </div> + +<div class="ui g-modal-confirm delete modal" id="delete-user-modal"> + <div class="header"> + {{svg "octicon-trash"}} + {{ctx.Locale.Tr "settings.delete_account_title"}} + </div> + <form class="ui form" method="post" action="./delete"> + <div class="content"> + <p>{{ctx.Locale.Tr "settings.delete_account_desc"}}</p> + {{$.CsrfTokenHtml}} + <div class="field"> + <div class="ui checkbox"> + <label for="purge">{{ctx.Locale.Tr "admin.users.purge"}}</label> + <input name="purge" type="checkbox"> + </div> + <p class="help">{{ctx.Locale.Tr "admin.users.purge_help"}}</p> + </div> + </div> + {{template "base/modal_actions_confirm" .}} + </form> +</div> + +{{template "admin/layout_footer" .}} diff --git a/templates/admin/user/list.tmpl b/templates/admin/user/list.tmpl new file mode 100644 index 0000000..e5d4299 --- /dev/null +++ b/templates/admin/user/list.tmpl @@ -0,0 +1,119 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin user")}} + <div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.users.user_manage_panel"}} ({{ctx.Locale.Tr "admin.total" .Total}}) + <div class="ui right"> + <a class="ui primary tiny button" href="{{AppSubUrl}}/admin/users/new">{{ctx.Locale.Tr "admin.users.new_account"}}</a> + </div> + </h4> + <div class="ui attached segment"> + <form class="ui form ignore-dirty" id="user-list-search-form"> + + <!-- Right Menu --> + <div class="ui right floated secondary filter menu"> + <!-- Status Filter Menu Item --> + <div class="ui dropdown type jump item"> + <span class="text">{{ctx.Locale.Tr "admin.users.list_status_filter.menu_text"}}</span> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="menu"> + <a class="item j-reset-status-filter">{{ctx.Locale.Tr "admin.users.list_status_filter.reset"}}</a> + <div class="divider"></div> + <label class="item"><input type="radio" name="status_filter[is_admin]" value="1"> {{ctx.Locale.Tr "admin.users.list_status_filter.is_admin"}}</label> + <label class="item"><input type="radio" name="status_filter[is_admin]" value="0"> {{ctx.Locale.Tr "admin.users.list_status_filter.not_admin"}}</label> + <div class="divider"></div> + <label class="item"><input type="radio" name="status_filter[is_active]" value="1"> {{ctx.Locale.Tr "admin.users.list_status_filter.is_active"}}</label> + <label class="item"><input type="radio" name="status_filter[is_active]" value="0"> {{ctx.Locale.Tr "admin.users.list_status_filter.not_active"}}</label> + <div class="divider"></div> + <label class="item"><input type="radio" name="status_filter[is_restricted]" value="0"> {{ctx.Locale.Tr "admin.users.list_status_filter.not_restricted"}}</label> + <label class="item"><input type="radio" name="status_filter[is_restricted]" value="1"> {{ctx.Locale.Tr "admin.users.list_status_filter.is_restricted"}}</label> + <div class="divider"></div> + <label class="item"><input type="radio" name="status_filter[is_prohibit_login]" value="0"> {{ctx.Locale.Tr "admin.users.list_status_filter.not_prohibit_login"}}</label> + <label class="item"><input type="radio" name="status_filter[is_prohibit_login]" value="1"> {{ctx.Locale.Tr "admin.users.list_status_filter.is_prohibit_login"}}</label> + <div class="divider"></div> + <label class="item"><input type="radio" name="status_filter[is_2fa_enabled]" value="1"> {{ctx.Locale.Tr "admin.users.list_status_filter.is_2fa_enabled"}}</label> + <label class="item"><input type="radio" name="status_filter[is_2fa_enabled]" value="0"> {{ctx.Locale.Tr "admin.users.list_status_filter.not_2fa_enabled"}}</label> + </div> + </div> + + <!-- Sort Menu Item --> + <div class="ui dropdown type jump item"> + <span class="text"> + {{ctx.Locale.Tr "repo.issues.filter_sort"}} + </span> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="menu"> + <button class="item" name="sort" value="oldest">{{ctx.Locale.Tr "repo.issues.filter_sort.oldest"}}</button> + <button class="item" name="sort" value="newest">{{ctx.Locale.Tr "repo.issues.filter_sort.latest"}}</button> + <button class="item" name="sort" value="alphabetically">{{ctx.Locale.Tr "repo.issues.label.filter_sort.alphabetically"}}</button> + <button class="item" name="sort" value="reversealphabetically">{{ctx.Locale.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</button> + <button class="item" name="sort" value="recentupdate">{{ctx.Locale.Tr "repo.issues.filter_sort.recentupdate"}}</button> + <button class="item" name="sort" value="leastupdate">{{ctx.Locale.Tr "repo.issues.filter_sort.leastupdate"}}</button> + </div> + </div> + </div> + + {{template "shared/search/combo" dict "Value" .Keyword "Placeholder" (ctx.Locale.Tr "search.user_kind")}} + </form> + </div> + <div class="ui attached table segment"> + <table class="ui very basic striped table unstackable"> + <thead> + <tr> + <th data-sortt-asc="oldest" data-sortt-desc="newest">ID{{SortArrow "oldest" "newest" .SortType false}}</th> + <th data-sortt-asc="alphabetically" data-sortt-desc="reversealphabetically" data-sortt-default="true"> + {{ctx.Locale.Tr "admin.users.name"}} + {{SortArrow "alphabetically" "reversealphabetically" $.SortType true}} + </th> + <th>{{ctx.Locale.Tr "email"}}</th> + <th>{{ctx.Locale.Tr "admin.users.activated"}}</th> + <th>{{ctx.Locale.Tr "admin.users.restricted"}}</th> + <th>{{ctx.Locale.Tr "admin.users.2fa"}}</th> + <th>{{ctx.Locale.Tr "admin.users.created"}}</th> + <th data-sortt-asc="lastlogin" data-sortt-desc="reverselastlogin"> + {{ctx.Locale.Tr "admin.users.last_login"}} + {{SortArrow "lastlogin" "reverselastlogin" $.SortType false}} + </th> + <th></th> + </tr> + </thead> + <tbody> + {{range .Users}} + <tr> + <td>{{.ID}}</td> + <td> + <a href="{{.HomeLink}}">{{.Name}}</a> + {{if .IsAdmin}} + <span class="ui mini label">{{ctx.Locale.Tr "admin.users.admin"}}</span> + {{else if eq 2 .Type}}{{/* Reserved user */}} + <span class="ui mini label">{{ctx.Locale.Tr "admin.users.reserved"}}</span> + {{else if eq 4 .Type}}{{/* Bot "user" */}} + <span class="ui mini label">{{ctx.Locale.Tr "admin.users.bot"}}</span> + {{else if eq 5 .Type}}{{/* Remote user */}} + <span class="ui mini label">{{ctx.Locale.Tr "admin.users.remote"}}</span> + {{end}} + </td> + <td class="gt-ellipsis tw-max-w-48">{{.Email}}</td> + <td>{{if .IsActive}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td> + <td>{{if .IsRestricted}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td> + <td>{{if index $.UsersTwoFaStatus .ID}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}</td> + <td>{{DateTime "short" .CreatedUnix}}</td> + {{if .LastLoginUnix}} + <td>{{DateTime "short" .LastLoginUnix}}</td> + {{else}} + <td><span>{{ctx.Locale.Tr "admin.users.never_login"}}</span></td> + {{end}} + <td> + <div class="tw-flex tw-gap-2"> + <a href="{{$.Link}}/{{.ID}}" data-tooltip-content="{{ctx.Locale.Tr "admin.users.details"}}">{{svg "octicon-person"}}</a> + <a href="{{$.Link}}/{{.ID}}/edit" data-tooltip-content="{{ctx.Locale.Tr "edit"}}">{{svg "octicon-pencil"}}</a> + </div> + </td> + </tr> + {{end}} + </tbody> + </table> + </div> + + {{template "base/paginate" .}} + </div> +{{template "admin/layout_footer" .}} diff --git a/templates/admin/user/new.tmpl b/templates/admin/user/new.tmpl new file mode 100644 index 0000000..b04ebc4 --- /dev/null +++ b/templates/admin/user/new.tmpl @@ -0,0 +1,90 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin new user")}} + <div class="admin-setting-content"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.users.new_account"}} + </h4> + <div class="ui attached segment"> + <form class="ui form" action="{{.Link}}" method="post"> + {{template "base/disable_form_autofill"}} + {{.CsrfTokenHtml}} + <!-- Types and name --> + <div class="inline required field {{if .Err_LoginType}}error{{end}}"> + <label>{{ctx.Locale.Tr "admin.users.auth_source"}}</label> + <div class="ui selection type dropdown"> + <input type="hidden" id="login_type" name="login_type" value="{{.login_type}}" data-password="required" required> + <div class="text">{{ctx.Locale.Tr "admin.users.local"}}</div> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="menu"> + <div class="item" data-value="0-0">{{ctx.Locale.Tr "admin.users.local"}}</div> + {{range .Sources}} + <div class="item" data-value="{{.Type.Int}}-{{.ID}}">{{.Name}}</div> + {{end}} + </div> + </div> + </div> + + <div class="inline field {{if .Err_Visibility}}error{{end}}"> + <span class="inline required field"><label for="visibility">{{ctx.Locale.Tr "settings.visibility"}}</label></span> + <div class="ui selection type dropdown"> + <input type="hidden" id="visibility" name="visibility" value="{{if .visibility}}{{printf "%d" .visibility}}{{else}}{{printf "%d" .DefaultUserVisibilityMode}}{{end}}"> + <div class="text"> + {{if .DefaultUserVisibilityMode.IsPublic}}{{ctx.Locale.Tr "settings.visibility.public"}}{{end}} + {{if .DefaultUserVisibilityMode.IsLimited}}{{ctx.Locale.Tr "settings.visibility.limited"}}{{end}} + {{if .DefaultUserVisibilityMode.IsPrivate}}{{ctx.Locale.Tr "settings.visibility.private"}}{{end}} + </div> + {{svg "octicon-triangle-down" 14 "dropdown icon"}} + <div class="menu"> + {{range $mode := .AllowedUserVisibilityModes}} + {{if $mode.IsPublic}} + <div class="item" data-tooltip-content="{{ctx.Locale.Tr "settings.visibility.public_tooltip"}}" data-value="0">{{ctx.Locale.Tr "settings.visibility.public"}}</div> + {{else if $mode.IsLimited}} + <div class="item" data-tooltip-content="{{ctx.Locale.Tr "settings.visibility.limited_tooltip"}}" data-value="1">{{ctx.Locale.Tr "settings.visibility.limited"}}</div> + {{else if $mode.IsPrivate}} + <div class="item" data-tooltip-content="{{ctx.Locale.Tr "settings.visibility.private_tooltip"}}" data-value="2">{{ctx.Locale.Tr "settings.visibility.private"}}</div> + {{end}} + {{end}} + </div> + </div> + </div> + + <div class="required non-local field {{if .Err_LoginName}}error{{end}} {{if eq .login_type "0-0"}}tw-hidden{{end}}"> + <label for="login_name">{{ctx.Locale.Tr "admin.users.auth_login_name"}}</label> + <input id="login_name" name="login_name" value="{{.login_name}}"> + </div> + <div class="required field {{if .Err_UserName}}error{{end}}"> + <label for="user_name">{{ctx.Locale.Tr "username"}}</label> + <input id="user_name" type="text" name="user_name" value="{{.user_name}}" autofocus required maxlength="40"> + </div> + <div class="required field {{if .Err_Email}}error{{end}}"> + <label for="email">{{ctx.Locale.Tr "email"}}</label> + <input id="email" name="email" type="email" value="{{.email}}" required> + </div> + <div class="required local field {{if .Err_Password}}error{{end}} {{if not (eq .login_type "0-0")}}tw-hidden{{end}}"> + <label for="password">{{ctx.Locale.Tr "password"}}</label> + <input id="password" name="password" type="password" autocomplete="new-password" value="{{.password}}" {{if eq .login_type "0-0"}}required{{end}}> + </div> + + <div class="inline field local {{if ne .login_type "0-0"}}tw-hidden{{end}}"> + <div class="ui checkbox"> + <label><strong>{{ctx.Locale.Tr "auth.allow_password_change"}}</strong></label> + <input name="must_change_password" type="checkbox" checked> + </div> + </div> + + <!-- Send register notify e-mail --> + {{if .CanSendEmail}} + <div class="inline field"> + <div class="ui checkbox"> + <label><strong>{{ctx.Locale.Tr "admin.users.send_register_notify"}}</strong></label> + <input name="send_notify" type="checkbox" {{if .send_notify}}checked{{end}}> + </div> + </div> + {{end}} + + <div class="field"> + <button class="ui primary button">{{ctx.Locale.Tr "admin.users.new_account"}}</button> + </div> + </form> + </div> + </div> +{{template "admin/layout_footer" .}} diff --git a/templates/admin/user/view.tmpl b/templates/admin/user/view.tmpl new file mode 100644 index 0000000..21943a8 --- /dev/null +++ b/templates/admin/user/view.tmpl @@ -0,0 +1,48 @@ +{{template "admin/layout_head" (dict "ctxData" . "pageClass" "admin view user")}} + +<div class="admin-setting-content"> + <div class="admin-responsive-columns"> + <div class="tw-flex-1"> + <h4 class="ui top attached header"> + {{.Title}} + <div class="ui right"> + <a class="ui primary tiny button" href="{{.Link}}/edit">{{ctx.Locale.Tr "admin.users.edit"}}</a> + </div> + </h4> + <div class="ui attached segment"> + {{template "admin/user/view_details" .}} + </div> + </div> + <div class="tw-flex-1"> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.emails"}} + <div class="ui right"> + {{.EmailsTotal}} + </div> + </h4> + <div class="ui attached segment"> + {{template "admin/user/view_emails" .}} + </div> + </div> + </div> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "admin.repositories"}} + <div class="ui right"> + {{.ReposTotal}} + </div> + </h4> + <div class="ui attached segment"> + {{template "explore/repo_list" .}} + </div> + <h4 class="ui top attached header"> + {{ctx.Locale.Tr "settings.organization"}} + <div class="ui right"> + {{.OrgsTotal}} + </div> + </h4> + <div class="ui attached segment"> + {{template "explore/user_list" .}} + </div> +</div> + +{{template "admin/layout_footer" .}} diff --git a/templates/admin/user/view_details.tmpl b/templates/admin/user/view_details.tmpl new file mode 100644 index 0000000..be2f32b --- /dev/null +++ b/templates/admin/user/view_details.tmpl @@ -0,0 +1,74 @@ +<div class="flex-list"> + <div class="flex-item"> + <div class="flex-item-leading"> + {{ctx.AvatarUtils.Avatar .User 48}} + </div> + <div class="flex-item-main"> + <div class="flex-item-title"> + {{template "shared/user/name" .User}} + {{if .User.IsAdmin}} + <span class="ui basic label">{{ctx.Locale.Tr "admin.users.admin"}}</span> + {{end}} + </div> + <div class="flex-item-body"> + <b>{{ctx.Locale.Tr "admin.users.auth_source"}}:</b> + {{if eq .LoginSource.ID 0}} + {{ctx.Locale.Tr "admin.users.local"}} + {{else}} + {{.LoginSource.Name}} + {{end}} + </div> + <div class="flex-item-body"> + <b>{{ctx.Locale.Tr "admin.users.activated"}}:</b> + {{if .User.IsActive}} + {{svg "octicon-check"}} + {{else}} + {{svg "octicon-x"}} + {{end}} + </div> + <div class="flex-item-body"> + <b>{{ctx.Locale.Tr "admin.users.restricted"}}:</b> + {{if .User.IsRestricted}} + {{svg "octicon-check"}} + {{else}} + {{svg "octicon-x"}} + {{end}} + </div> + <div class="flex-item-body"> + <b>{{ctx.Locale.Tr "settings.visibility"}}:</b> + {{if .User.Visibility.IsPublic}}{{ctx.Locale.Tr "settings.visibility.public"}}{{end}} + {{if .User.Visibility.IsLimited}}{{ctx.Locale.Tr "settings.visibility.limited"}}{{end}} + {{if .User.Visibility.IsPrivate}}{{ctx.Locale.Tr "settings.visibility.private"}}{{end}} + </div> + <div class="flex-item-body"> + <b>{{ctx.Locale.Tr "admin.users.2fa"}}:</b> + {{if .TwoFactorEnabled}} + <span class="text green">{{svg "octicon-check"}}</span> + {{else}} + {{svg "octicon-x"}} + {{end}} + </div> + {{if .User.Language}} + <div class="flex-item-body"> + <span class="flex-text-inline"> + <b>{{ctx.Locale.Tr "settings.language"}}:</b> + {{range .AllLangs}}{{if eq $.User.Language .Lang}}{{.Name}}{{end}}{{end}} + </span> + </div> + {{end}} + {{if .User.Location}} + <div class="flex-item-body"> + <span class="flex-text-inline">{{svg "octicon-location"}}{{.User.Location}}</span> + </div> + {{end}} + {{if .User.Website}} + <div class="flex-item-body"> + <span class="flex-text-inline"> + {{svg "octicon-link"}} + <a target="_blank" href="{{.User.Website}}">{{.User.Website}}</a> + </span> + </div> + {{end}} + </div> + </div> +</div> diff --git a/templates/admin/user/view_emails.tmpl b/templates/admin/user/view_emails.tmpl new file mode 100644 index 0000000..22ce305 --- /dev/null +++ b/templates/admin/user/view_emails.tmpl @@ -0,0 +1,19 @@ +<div class="flex-list"> + {{range .Emails}} + <div class="flex-item"> + <div class="flex-item-main"> + <div class="flex-text-block"> + {{.Email}} + {{if .IsPrimary}} + <div class="ui primary label">{{ctx.Locale.Tr "settings.primary"}}</div> + {{end}} + {{if .IsActivated}} + <div class="ui green label">{{ctx.Locale.Tr "settings.activated"}}</div> + {{else}} + <div class="ui label">{{ctx.Locale.Tr "settings.requires_activation"}}</div> + {{end}} + </div> + </div> + </div> + {{end}} +</div> |