Merge branch 'main' into xormigrate

This commit is contained in:
qwerty287 2024-10-09 16:24:40 +03:00 committed by GitHub
commit dd1fbd4380
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 668 additions and 62 deletions

View File

@ -408,6 +408,10 @@ func (u *User) IsIndividual() bool {
return u.Type == UserTypeIndividual
}
func (u *User) IsUser() bool {
return u.Type == UserTypeIndividual || u.Type == UserTypeBot
}
// IsBot returns whether or not the user is of type bot
func (u *User) IsBot() bool {
return u.Type == UserTypeBot

View File

@ -111,12 +111,12 @@ func SetExecutablePath(path string) error {
func ensureGitVersion() error {
if !DefaultFeatures().CheckVersionAtLeast(RequiredVersion) {
moreHint := "get git: https://git-scm.com/download/"
moreHint := "get git: https://git-scm.com/downloads"
if runtime.GOOS == "linux" {
// there are a lot of CentOS/RHEL users using old git, so we add a special hint for them
if _, err := os.Stat("/etc/redhat-release"); err == nil {
// ius.io is the recommended official(git-scm.com) method to install git
moreHint = "get git: https://git-scm.com/download/linux and https://ius.io"
moreHint = "get git: https://git-scm.com/downloads/linux and https://ius.io"
}
}
return fmt.Errorf("installed git version %q is not supported, Gitea requires git version >= %q, %s", DefaultFeatures().gitVersion.Original(), RequiredVersion, moreHint)

View File

@ -580,6 +580,8 @@ lang_select_error=Sélectionnez une langue dans la liste.
username_been_taken=Le nom d'utilisateur est déjà pris.
username_change_not_local_user=Les utilisateurs non-locaux n'ont pas le droit de modifier leur nom d'utilisateur.
change_username_disabled=Le changement de nom dutilisateur est désactivé.
change_full_name_disabled=Le changement de nom complet est désactivé.
username_has_not_been_changed=Le nom d'utilisateur n'a pas été modifié
repo_name_been_taken=Ce nom de dépôt est déjà utilisé.
repository_force_private=Force Private est activé : les dépôts privés ne peuvent pas être rendus publics.
@ -1039,6 +1041,7 @@ issue_labels_helper=Sélectionner un jeu de label.
license=Licence
license_helper=Sélectionner une licence
license_helper_desc=Une licence réglemente ce que les autres peuvent ou ne peuvent pas faire avec votre code. Vous ne savez pas laquelle est la bonne pour votre projet ? Comment <a target="_blank" rel="noopener noreferrer" href="%s">choisir une licence</a>.
multiple_licenses=Licences multiples
object_format=Format d'objet
object_format_helper=Format dobjet pour ce dépôt. Ne peut être modifié plus tard. SHA1 est le plus compatible.
readme=LISEZMOI
@ -1834,7 +1837,7 @@ pulls.is_empty=Les changements sur cette branche sont déjà sur la branche cibl
pulls.required_status_check_failed=Certains contrôles requis n'ont pas réussi.
pulls.required_status_check_missing=Certains contrôles requis sont manquants.
pulls.required_status_check_administrator=En tant qu'administrateur, vous pouvez toujours fusionner cette requête de pull.
pulls.blocked_by_approvals=Cette demande d'ajout nest pas suffisamment approuvée. %d approbations obtenues sur %d.
pulls.blocked_by_approvals=Cette demande dajout nest pas suffisamment approuvée. %d approbations obtenues sur %d.
pulls.blocked_by_approvals_whitelisted=Cette demande dajout na pas encore assez dapprobations. %d sur %d approbations de la part des utilisateurs ou équipes sur la liste autorisée.
pulls.blocked_by_rejection=Cette demande dajout nécessite des corrections sollicitées par un évaluateur officiel.
pulls.blocked_by_official_review_requests=Cette demande dajout a des sollicitations officielles dévaluation.
@ -2940,6 +2943,7 @@ dashboard.start_schedule_tasks=Démarrer les tâches planifiées
dashboard.sync_branch.started=Début de la synchronisation des branches
dashboard.sync_tag.started=Synchronisation des étiquettes
dashboard.rebuild_issue_indexer=Reconstruire lindexeur des tickets
dashboard.sync_repo_licenses=Synchroniser les licences du dépôt
users.user_manage_panel=Gestion du compte utilisateur
users.new_account=Créer un compte

View File

@ -2890,17 +2890,167 @@ dashboard.delete_generated_repository_avatars=Scrios abhatáranna stórtha ginte
dashboard.sync_repo_branches=Sync brainsí caillte ó shonraí git go bunachair sonraí
dashboard.sync_repo_tags=Clibeanna sioncraigh ó shonraí git go bunachar sonraí
dashboard.update_mirrors=Scátháin a nuashonrú
dashboard.repo_health_check=Seiceáil sláinte gach stóras
dashboard.check_repo_stats=Seiceáil gach staitisticí stórais
dashboard.archive_cleanup=Scrios sean-chartlanna stórais
dashboard.deleted_branches_cleanup=Brainsí scriosta a ghlanadh
dashboard.update_migration_poster_id=Nuashonraigh ID póstaer imir
dashboard.git_gc_repos=Bailíonn truflais gach stórais
dashboard.resync_all_sshkeys=Nuashonraigh an comhad '.ssh/authorized_keys' le heochracha Gitea SSH.
dashboard.resync_all_sshprincipals=Nuashonraigh an comhad '.ssh/authorized_principals' le príomhphrionsabail Gitea SSH.
dashboard.resync_all_hooks=Athshioncrónaigh crúcaí réamhfhála, nuashonraithe agus iar-fhála na stórtha go léir.
dashboard.reinit_missing_repos=Aththosaigh gach stórais Git atá in easnamh a bhfuil taifid ann dóibh
dashboard.sync_external_users=Sioncrónaigh sonraí úsáideoirí seachtracha
dashboard.cleanup_hook_task_table=Tábla hook_task glantacháin
dashboard.cleanup_packages=Pacáistí glanta in éag
dashboard.cleanup_actions=Gníomhaíochtaí glanta in éag acmhainní
dashboard.server_uptime=Aga fónaimh Freastalaí
dashboard.current_goroutine=Goroutines Reatha
dashboard.current_memory_usage=Úsáid Cuimhne Reatha
dashboard.total_memory_allocated=Cuimhne Iomlán Leithdháilte
dashboard.memory_obtained=Cuimhne Faighte
dashboard.pointer_lookup_times=Amanna Cuardaigh Pointeora
dashboard.memory_allocate_times=Leithdháiltí Cuimhne
dashboard.memory_free_times=Saorálann Cuimhne
dashboard.current_heap_usage=Úsáid Charn Reatha
dashboard.heap_memory_obtained=Cuimhne Charn Faighte
dashboard.heap_memory_idle=Díomhaoin Cuimhne Carn
dashboard.heap_memory_in_use=Cuimhne Carm In Úsáid
dashboard.heap_memory_released=Cuimhne Carn Eisithe
dashboard.heap_objects=Cuspóirí Carn
dashboard.bootstrap_stack_usage=Úsáid Staca Bootstrap
dashboard.stack_memory_obtained=Cuimhne Staca Faighte
dashboard.mspan_structures_usage=Úsáid Struchtúir MSpan
dashboard.mspan_structures_obtained=Struchtúir MSpan a Faightear
dashboard.mcache_structures_usage=Úsáid Struchtúir MCache
dashboard.mcache_structures_obtained=Struchtúir MCache a Faightear
dashboard.profiling_bucket_hash_table_obtained=Tábla Hash Buicéad Próifílithe a Faightear
dashboard.gc_metadata_obtained=Meiteashonraí GC faighte
dashboard.other_system_allocation_obtained=Leithdháileadh Córais Eile a Fuarthas
dashboard.next_gc_recycle=Athchúrsáil GC Eile
dashboard.last_gc_time=Ó Am Deiridh GC
dashboard.total_gc_time=Sos Iomlán GC
dashboard.total_gc_pause=Sos Iomlán GC
dashboard.last_gc_pause=Sos GC Deireanach
dashboard.gc_times=Amanna GC
dashboard.delete_old_actions=Scrios gach sean-ghníomhaíocht ón mbunachar
dashboard.delete_old_actions.started=Scrios na sean-ghníomhaíocht go léir ón mbunachar sonraí tosaithe.
dashboard.update_checker=Seiceoir nuashonraithe
dashboard.delete_old_system_notices=Scrios gach seanfhógra córais ón mbunachar sonraí
dashboard.gc_lfs=Bailigh truflais meta rudaí LFS
dashboard.stop_zombie_tasks=Stad gníomhartha tascanna zombie
dashboard.stop_endless_tasks=Stad gníomhartha tascanna gan deireadh
dashboard.cancel_abandoned_jobs=Cealaigh gníomhartha poist tréigthe
dashboard.start_schedule_tasks=Tosaigh tascanna sceideal gníom
dashboard.sync_branch.started=Thosaigh Brainsí Sioncronú
dashboard.sync_tag.started=Clibeanna Thosaigh Sioncronú
dashboard.rebuild_issue_indexer=Atógáil innéacsóir eisiúna
dashboard.sync_repo_licenses=Sioncronaigh ceadúnais repo
users.user_manage_panel=Bainistíocht Cuntas Úsáideora
users.new_account=Cruthaigh cuntas Úsáideora
users.name=Ainm úsáideora
users.full_name=Ainm Iomlán
users.activated=Gníomhachtaithe
users.admin=Riarachán
users.restricted=Srianta
users.reserved=In áirithe
users.bot=Bota
users.remote=Iargúlta
users.2fa=2FA
users.repos=Stórais
users.created=Cruthaithe
users.last_login=Sínigh Isteach Deiridh
users.never_login=Ná Sínigh Isteach riamh
users.send_register_notify=Seol Fógra um Chlárú Úsáideora
users.new_success=Tá an cuntas úsáideora "%s" cruthaithe.
users.edit=Eagar
users.auth_source=Foinse Fíordheimhnithe
users.local=Áitiúil
users.auth_login_name=Ainm Síniú Isteach Fíordheimhnithe
users.password_helper=Fág an pasfhocal folamh chun é a choinneáil gan athrú.
users.update_profile_success=Nuashonraíodh an cuntas úsáideora.
users.edit_account=Cuir Cuntas Úsáideora in Eagar
users.max_repo_creation=Uasmhéid Stóras
users.max_repo_creation_desc=(Cuir isteach -1 chun an teorainn réamhshocraithe domhanda a úsáid.)
users.is_activated=Gníomhachtaítear Cuntas Úsáideora
users.prohibit_login=Díchumasaigh Síniú Isteach
users.is_admin=Is Riarthóir
users.is_restricted=Is Srianta
users.allow_git_hook=Féadfaidh Git Hooks a Chruthú
users.allow_git_hook_tooltip=Déantar Git Hooks a fhorghníomhú mar úsáideoir OS a ritheann Gitea agus beidh an leibhéal céanna rochtana óstaigh aige. Mar thoradh air sin, is féidir le húsáideoirí a bhfuil an phribhléid speisialta Git Hook seo acu rochtain a fháil ar gach stór Gitea agus iad a mhodhnú chomh maith leis an mbunachar sonraí a úsáideann Gitea. Dá bharr sin tá siad in ann pribhléidí riarthóra Gitea a fháil freisin.
users.allow_import_local=Is féidir Stórais Áitiúla a Allmhairiú
users.allow_create_organization=Is féidir Eagraíochtaí a Chruthú
users.update_profile=Nuashonraigh Cuntas Úsáideora
users.delete_account=Scrios Cuntas Úsáide
users.cannot_delete_self=Ní féidir leat tú féin a scriosadh
users.still_own_repo=Tá stórais amháin nó níos mó fós ag an úsáideoir seo. Scrios nó aistrigh na stórais seo ar dtús.
users.still_has_org=Is ball d'eagraíocht é an t-úsáideoir seo. Bain an t-úsáideoir ó aon eagraíochtaí ar dtús.
users.purge=Úsáideoir a Ghlanadh
users.purge_help=Scrios go héigeantach úsáideoir agus aon stórais, eagraíochtaí agus pacáistí atá faoi úinéireacht an úsáideora. Scriosfar gach trácht freisin.
users.still_own_packages=Tá pacáiste amháin nó níos mó fós ag an úsáideoir seo, scrios na pacáistí seo ar dtús.
users.deletion_success=Scriosadh an cuntas úsáideora.
users.reset_2fa=Athshocraigh 2FA
users.list_status_filter.menu_text=Scagaire
users.list_status_filter.reset=Athshocraigh
users.list_status_filter.is_active=Gníomhach
users.list_status_filter.not_active=Neamhghníomhach
users.list_status_filter.is_admin=Riarachán
users.list_status_filter.not_admin=Ní Riarachán
users.list_status_filter.is_restricted=Srianta
users.list_status_filter.not_restricted=Gan Srian
users.list_status_filter.is_prohibit_login=Cosc ar Logáil Isteach
users.list_status_filter.not_prohibit_login=Ceadaigh Logáil isteach
users.list_status_filter.is_2fa_enabled=2FA Cumasaithe
users.list_status_filter.not_2fa_enabled=2FA faoi mhíchumas
users.details=Sonraí Úsáideora
emails.email_manage_panel=Bainistíocht Ríomhphost Úsáideoir
emails.primary=Bunscoile
emails.activated=Gníomhachtaithe
emails.filter_sort.email=Ríomhphost
emails.filter_sort.email_reverse=Ríomhphost (droim ar ais)
emails.filter_sort.name=Ainm Úsáideora
emails.filter_sort.name_reverse=Ainm Úsáideora (droim ar ais)
emails.updated=Nuashonraíodh an ríomhphost
emails.not_updated=Theip ar an seoladh ríomhphoist iarrtha a nuashonrú: %v
emails.duplicate_active=Tá an seoladh ríomhphoist seo gníomhach cheana féin d'úsáideoir difriúil.
emails.change_email_header=Nuashonraigh Airíonna Ríomhphoist
emails.change_email_text=An bhfuil tú cinnte gur mhaith leat an seoladh ríomhphoist seo a nuashonrú?
emails.delete=Scrios Ríomhphost
emails.delete_desc=An bhfuil tú cinnte gur mhaith leat an seoladh ríomhphoist seo a scriosadh?
emails.deletion_success=Tá an seoladh ríomhphoist scriosta.
emails.delete_primary_email_error=Ní féidir leat an ríomhphost príomhúil a scriosadh.
orgs.org_manage_panel=Bainistíocht Eagraíochta
orgs.name=Ainm
orgs.teams=Foirne
orgs.members=Comhaltaí
orgs.new_orga=Eagraíocht Nua
repos.repo_manage_panel=Bainistíocht Stórais
repos.unadopted=Stórais Neamhghlactha
repos.unadopted.no_more=Níor aimsíodh níos mó stórais neamhghlactha
repos.owner=Úinéir
repos.name=Ainm
repos.private=Príobháideach
repos.issues=Saincheisteanna
repos.size=Méid
repos.lfs_size=Méid LFS
packages.package_manage_panel=Bainistíocht Pacáiste
packages.total_size=Méid Iomlán: %s
packages.unreferenced_size=Méid gan tagairt: %s
packages.cleanup=Glan suas sonraí in éag
packages.cleanup.success=Glanadh suas sonraí in éag go rathúil
packages.owner=Úinéir
packages.creator=Cruthaitheoir
packages.name=Ainm
packages.version=Leagan
packages.type=Cineál
packages.repository=Stóráil
packages.size=Méid
packages.published=Foilsithe
defaulthooks=Réamhshocraithe Crúcaí Gréasán
defaulthooks.desc=Déanann Crúcaí Gréasán iarratais HTTP POST go huathoibríoch chuig freastalaí nuair a chuireann imeachtaí áirithe Gitea tús. Is mainneachtainí iad na cuacha gréasáin a shainítear anseo agus déanfar iad a chóipeáil isteach i ngach stórais nua. Léigh tuilleadh sa <a target="_blank" rel="noopener" href="%s">treoir chúca Crúcaí Gréasán</a>.
@ -2912,49 +3062,375 @@ systemhooks.desc=Déanann Crúcaí Gréasán iarratais HTTP POST go huathoibrío
systemhooks.add_webhook=Cuir Crúca Gréasán Córas leis
systemhooks.update_webhook=Nuashonraigh Córas Crúca Gréasán
auths.auth_manage_panel=Bainistiú Foinse Fíordheimhnithe
auths.new=Cuir Foinse Fíordheimhni
auths.name=Ainm
auths.type=Cineál
auths.enabled=Cumasaithe
auths.syncenabled=Cumasaigh Sioncrónú Úsáideora
auths.updated=Nuashonraithe
auths.auth_type=Cineál Fíordheimhnithe
auths.auth_name=Ainm Fíordheimhnithe
auths.security_protocol=Prótacal Slándála
auths.domain=Fearann
auths.host=Óstach
auths.port=Calafort
auths.bind_dn=Ceangail DN
auths.bind_password=Ceangail Pasfhocal
auths.user_base=Bonn Cuardaigh Úsáideora
auths.user_dn=Úsáideoir DN
auths.attribute_username=Tréith Ainm Úsáideora
auths.attribute_username_placeholder=Fág folamh chun an t-ainm úsáideora a iontráiltear i Gitea a úsáid.
auths.attribute_name=Tréith Céad Ainm
auths.attribute_surname=Tréith Sloinne
auths.attribute_mail=Tréith ríomhphoist
auths.attribute_ssh_public_key=Tréith Eochair SSH Phoiblí
auths.attribute_avatar=Tréith Avatar
auths.attributes_in_bind=Faigh tréithe i gComhthéacs Bind DN
auths.allow_deactivate_all=Lig do thoradh cuardaigh folamh gach úsáideoir a dhíghníomhachtú
auths.use_paged_search=Úsáid Cuardach Leathanaigh
auths.search_page_size=Méid an Leathanaigh
auths.filter=Scagaire Úsáideora
auths.admin_filter=Scagaire Riaracháin
auths.restricted_filter=Scagaire Srianta
auths.restricted_filter_helper=Fág folamh chun aon úsáideoirí a shocrú mar theoranta. Úsáid réiltín ('*') chun gach úsáideoir nach meaitseálann Scagaire Riaracháin a shocrú mar theoranta.
auths.verify_group_membership=Fíoraigh ballraíocht ghrúpa i LDAP (fág an scagaire folamh le scipeáil)
auths.group_search_base=Bonn Cuardaigh Grúpa DN
auths.group_attribute_list_users=Tréith Grúpa ina bhfuil Liosta Úsáideoirí
auths.user_attribute_in_group=Tréith Úsáideora atá Liostaithe i nGrúpa
auths.map_group_to_team=Léarscáil grúpaí LDAP chuig foirne na hEagraíochta (fág an réimse folamh le scipeáil)
auths.map_group_to_team_removal=Bain úsáideoirí ó fhoirne sioncronaithe mura mbaineann an t-úsáideoir leis an ngrúpa comhfhreagrach LDAP
auths.enable_ldap_groups=Cumasaigh grúpaí LDAP
auths.ms_ad_sa=MS AD Tréithe Cuardaigh
auths.smtp_auth=Cineál Fíordheimhnithe SMTP
auths.smtphost=Óstach SMTP
auths.smtpport=SMTP Calafort
auths.allowed_domains=Fearainn Ceadaithe
auths.allowed_domains_helper=Fág folamh chun gach fearann a cheadú. Déan ilfhearann a scaradh le camóg (',').
auths.skip_tls_verify=Scipeáil Fíorú TLS
auths.force_smtps=Fórsa SMTPS
auths.force_smtps_helper=Úsáidtear SMTPS i gcónaí ar chalafort 465. Socraigh é seo chun SMTPS a chur i bhfeidhm ar chalafoirt eile. (Seachas sin úsáidfear STARTTLS ar chalafoirt eile má thacaíonn an t-óstach leis.)
auths.helo_hostname=Ainm Óstach HELO
auths.helo_hostname_helper=Ainm óstach a sheoltar le HELO. Fág bán chun an t-ainm óstach reatha a sheoladh.
auths.disable_helo=Díchumasaigh HELO
auths.pam_service_name=Ainm Seirbhíse PAM
auths.pam_email_domain=Fearann Ríomhphoist PAM (roghnach)
auths.oauth2_provider=Soláthraí OAuth2
auths.oauth2_icon_url=URL deilbhín
auths.oauth2_clientID=Aitheantas Cliant (Eochair)
auths.oauth2_clientSecret=Rúnda Cliant
auths.openIdConnectAutoDiscoveryURL=URL Fionnachtana Uathoibríoch OpenID Connect
auths.oauth2_use_custom_url=Úsáid URLanna Saincheaptha in ionad URLanna Réamhshocraithe
auths.oauth2_tokenURL=URL Comhartha
auths.oauth2_authURL=Údaraigh URL
auths.oauth2_profileURL=URL Próifíl
auths.oauth2_emailURL=URL ríomhphoist
auths.skip_local_two_fa=Scipeáil 2FA áitiúil
auths.skip_local_two_fa_helper=Ciallaíonn fágáil gan socrú go mbeidh ar úsáideoirí áitiúla a bhfuil tacar 2FA acu 2FA a rith fós chun logáil isteach
auths.oauth2_tenant=Tionónta
auths.oauth2_scopes=Scóipeanna Breise
auths.oauth2_required_claim_name=Ainm Éilimh Riachtanach
auths.oauth2_required_claim_name_helper=Socraigh an t-ainm seo chun logáil isteach ón bhfoinse seo a shrianadh d'úsáideoirí a bhfuil éileamh acu leis an ainm seo
auths.oauth2_required_claim_value=Luach Éilimh Riachtanach
auths.oauth2_required_claim_value_helper=Socraigh an luach seo chun logáil isteach ón bhfoinse seo a shrianadh chuig úsáideoirí a bhfuil éileamh acu leis an ainm agus an luach seo
auths.oauth2_group_claim_name=Ainm éileamh ag soláthar ainmneacha grúpa don fhoinse seo (Roghnach)
auths.oauth2_admin_group=Luach Éilimh Grúpa d'úsáideoirí riarthóra. (Roghnach - teastaíonn ainm éilimh thuas)
auths.oauth2_restricted_group=Luach Éilimh Grúpa d'úsáideoirí srianta. (Roghnach - teastaíonn ainm éilimh thuas)
auths.oauth2_map_group_to_team=Map mhaígh grúpaí chuig foirne Eagraíochta. (Roghnach - éilíonn ainm an éilimh thuas)
auths.oauth2_map_group_to_team_removal=Bain úsáideoirí ó fhoirne sioncronaithe mura mbaineann an t-úsáideoir leis an ngrúpa comhfhreagrach.
auths.enable_auto_register=Cumasaigh Clárú Auto
auths.sspi_auto_create_users=Cruthaigh úsáideoirí go huathoibríoch
auths.sspi_auto_create_users_helper=Lig do mhodh auth SSPI cuntais nua a chruthú go huathoibríoch d'úsáideoirí a logálann isteach den chéad uair
auths.sspi_auto_activate_users=Gníomhachtaigh úsáideoirí go huathoibríoch
auths.sspi_auto_activate_users_helper=Lig modh auth SSPI úsáideoirí nua a ghníomhachtú go huathoibríoch
auths.sspi_strip_domain_names=Bain ainmneacha fearann ó ainm úsáideora
auths.sspi_strip_domain_names_helper=Má dhéantar iad a sheiceáil, bainfear ainmneacha fearainn ó ainmneacha logála isteach (m.sh. Beidh “DOMAIN\ user” agus "user@example.org" araon ní bheidh ach “úsáideoir”).
auths.sspi_separator_replacement=Deighilteoir le húsáid in ionad\,/agus @
auths.sspi_separator_replacement_helper=An carachtar a úsáidfear chun na deighilteoirí a chur in ionad na n-ainmneacha logála síos-leibhéil (m.sh. an \ i "DOMAIN\úsáideoir") agus ainmneacha príomhoidí úsáideora (m.sh. an @ in "user@example.org").
auths.sspi_default_language=Teanga úsáideora réamhshocraithe
auths.sspi_default_language_helper=Teanga réamhshocraithe d'úsáideoirí cruthaithe go huathoibríoch ag modh auth SSPI. Fág folamh más fearr leat teanga a bhrath go huathoibríoch.
auths.tips=Leideanna
auths.tips.oauth2.general=OAuth2 Fíordheimhniú
auths.tips.oauth2.general.tip=Agus fíordheimhniú OAuth2 nua á chlárú agat, ba chóir go mbeadh an URL glaonna ais/atreoraithe:
auths.tip.oauth2_provider=Soláthraí OAuth2
auths.tip.bitbucket=Cláraigh tomhaltóir OAuth nua ar %s agus cuir an cead 'Cuntas' - 'Léigh' leis
auths.tip.nextcloud=`Cláraigh tomhaltóir OAuth nua ar do chás ag baint úsáide as an roghchlár seo a leanas "Socruithe -> Slándáil -> cliant OAuth 2.0"`
auths.tip.dropbox=Cruthaigh feidhmchlár nua ag %s
auths.tip.facebook=Cláraigh feidhmchlár nua ag %s agus cuir an táirge "Facebook Login" leis
auths.tip.github=Cláraigh feidhmchlár OAuth nua ar %s
auths.tip.gitlab_new=Cláraigh feidhmchlár nua ar %s
auths.tip.google_plus=Faigh dintiúir chliaint OAuth2 ó chonsól API Google ag %s
auths.tip.openid_connect=Úsáid URL Fionnachtana OpenID Connect "https://{server}/.well-known/openid-configuration" chun na críochphointí a shonrú
auths.tip.twitter=Téigh go %s, cruthaigh feidhmchlár agus cinntigh go bhfuil an rogha "Ceadaigh úsáid a bhaint as an bhfeidhmchlár seo chun logáil isteach le Twitter" cumasaithe
auths.tip.discord=Cláraigh feidhmchlár nua ar %s
auths.tip.gitea=Cláraigh feidhmchlár OAuth2 nua. Tá treoir le fáil ag %s
auths.tip.yandex=`Cruthaigh feidhmchlár nua ag %s. Roghnaigh na ceadanna seo a leanas ón rannán "Yandex.Passport API": "Rochtain ar sheoladh ríomhphoist", "Rochtain ar avatar úsáideora" agus "Rochtain ar ainm úsáideora, céad ainm agus sloinne, inscne"`
auths.tip.mastodon=Ionchur URL sampla saincheaptha don shampla mastodon is mian leat a fhíordheimhniú leis (nó bain úsáid as an gceann réamhshocraithe)
auths.edit=Cuir Foinse Fíordheimhnithe in Eagar
auths.activated=Tá an Foinse Fíordheimhnithe seo gníomhachtaithe
auths.new_success=Tá an fíordheimhniú "%s" curtha leis.
auths.update_success=Nuashonraíodh an fhoinse fíordheimhnithe.
auths.update=Nuashonraigh Foinse Fíordheimhnithe
auths.delete=Scrios Foinse Fíordheimhnithe
auths.delete_auth_title=Scrios Foinse Fíordheimhnithe
auths.delete_auth_desc=Má scriosann tú foinse fíordheimhnithe cuirtear cosc ar úsáideoirí í a úsáid chun síniú isteach. Lean ort?
auths.still_in_used=Tá an fhoinse fíordheimhnithe fós in úsáid. Tiontaigh nó scrios aon úsáideoir a úsáideann an fhoinse fíordheimhnithe seo ar dtús.
auths.deletion_success=Tá an fhoinse fíordheimhnithe scriosta.
auths.login_source_exist=Tá an fhoinse fíordheimhnithe "%s" ann cheana.
auths.login_source_of_type_exist=Tá foinse fíordheimhnithe den chineál seo ann cheana féin.
auths.unable_to_initialize_openid=Ní féidir Soláthraí Ceangail OpenID a thionscnamh: %s
auths.invalid_openIdConnectAutoDiscoveryURL=URL Neamhbhailí Fionnachtana Uathoibríoch (ní mór gur URL bailí é seo ag tosú le http:// nó https://)
config.server_config=Cumraíocht Freastalaí
config.app_name=Teideal an Láithreáin
config.app_ver=Leagan Gitea
config.app_url=URL Bonn Gitea
config.custom_conf=Cosán Comhad Cumraíochta
config.custom_file_root_path=Cosán Fréamh Comhad Saincheaptha
config.domain=Fearann Freastalaí
config.offline_mode=Mód Áitiúil
config.disable_router_log=Díchumasaigh Loga an Ródaire
config.run_user=Rith Mar Ainm úsáideora
config.run_mode=Mód Rith
config.git_version=Leagan Git
config.app_data_path=Cosán Sonraí Aip
config.repo_root_path=Cosán Fréimhe Stórála
config.lfs_root_path=Cosán Fréamh LFS
config.log_file_root_path=Cosán Logála
config.script_type=Cineál Script
config.reverse_auth_user=Úsáideoir Fíordheimhnithe Droim ar Ais
config.ssh_config=Cumraíocht SSH
config.ssh_enabled=Cumasaithe
config.ssh_start_builtin_server=Úsáid Freastalaí Ionsuite
config.ssh_domain=Fearainn Freastalaí SSH
config.ssh_port=Calafort
config.ssh_listen_port=Éist Calafort
config.ssh_root_path=Cosán Fréimhe
config.ssh_key_test_path=Cosán Tástáil Eochair
config.ssh_keygen_path=Keygen ('ssh-keygen') Cosán
config.ssh_minimum_key_size_check=Seiceáil Íosta Méid Eochair
config.ssh_minimum_key_sizes=Méideanna Íosta Eochrach
config.lfs_config=Cumraíocht LFS
config.lfs_enabled=Cumasaithe
config.lfs_content_path=Cosán Ábhar LFS
config.lfs_http_auth_expiry=Éag Auth LFS HTTP
config.db_config=Cumraíocht Bunachar Sonraí
config.db_type=Cineál
config.db_host=Óstach
config.db_name=Ainm
config.db_user=Ainm úsáideora
config.db_schema=Scéim
config.db_ssl_mode=SSL
config.db_path=Cosán
config.service_config=Cumraíocht Seirbhíse
config.register_email_confirm=Deimhniú Ríomhphost a éileamh chun Clárú
config.disable_register=Díchumasaigh Féin-Chlárú
config.allow_only_internal_registration=Ceadaigh Clárú Amháin Trí Gitea féin
config.allow_only_external_registration=Ceadaigh Clárú Trí Sheirbhísí Seachtracha amháin
config.enable_openid_signup=Cumasaigh Féinchlárú OpenID
config.enable_openid_signin=Cumasaigh Síniú isteach OpenID
config.show_registration_button=Taispeáin Cnaipe Cláraithe
config.require_sign_in_view=Teastaíonn Sínigh isteach chun Leathanaigh Amharc
config.mail_notify=Cumasaigh Fógraí Ríomhphoist
config.enable_captcha=Cumasaigh CAPTCHA
config.active_code_lives=Saol Gníomhach ag an gCód
config.reset_password_code_lives=Am Éaga Chóid Aisghabhála Cuntais
config.default_keep_email_private=Folaigh Seoltaí Ríomhphoist de réir Réamhshocrú
config.default_allow_create_organization=Ceadaigh Cruthú Eagraíochtaí de réir Réamhshocrú
config.enable_timetracking=Cumasaigh Rianú Ama
config.default_enable_timetracking=Cumasaigh Rianú Ama de réir Réamhshocrú
config.default_allow_only_contributors_to_track_time=Lig do Rannpháirtithe Amháin Rianú Am
config.no_reply_address=Fearann Ríomhphoist Folaithe
config.default_visibility_organization=Infheictheacht réamhshocraithe d'Eagraíochtaí nua
config.default_enable_dependencies=Cumasaigh Spleáchais Eisithe de réir Réamhshocrú
config.webhook_config=Cumraíocht Crúca Gréasán
config.queue_length=Fad scuaine
config.deliver_timeout=Teorainn Ama Seachadta
config.skip_tls_verify=Scipeáil Fíorú TLS
config.mailer_config=Cumraíocht Seoltóra
config.mailer_enabled=Cumasaithe
config.mailer_enable_helo=Cumasaigh HELO
config.mailer_name=Ainm
config.mailer_protocol=Prótacal
config.mailer_smtp_addr=Seoladh SMTP
config.mailer_smtp_port=Calafort SMTP
config.mailer_user=Úsáideoir
config.mailer_use_sendmail=Úsáid Sendmail
config.mailer_sendmail_path=Cosán Sendmail
config.mailer_sendmail_args=Argóintí Breise chuig Sendmail
config.mailer_sendmail_timeout=Teorainn Ama Sendmail
config.mailer_use_dummy=Caochadán
config.test_email_placeholder=Ríomhphost (m.sh. test@example.com)
config.send_test_mail=Seol Ríomhphost Tástála
config.send_test_mail_submit=Seol
config.test_mail_failed=Theip ar ríomhphost tástála a sheoladh chuig "%s": %v
config.test_mail_sent=Tá ríomhphost tástála seolta chuig "%s".
config.oauth_config=Cumraíocht OAuth
config.oauth_enabled=Cumasaithe
config.cache_config=Cumraíocht taisce
config.cache_adapter=Cuibheoir taisce
config.cache_interval=Eatramh Taisce
config.cache_conn=Ceangal Taisce
config.cache_item_ttl=Mír Taisce TTL
config.cache_test=Taisce Tástáil
config.cache_test_failed=Theip ar an taisce a thaiscéaladh: %v.
config.cache_test_slow=D'éirigh leis an tástáil taisce, ach tá an freagra mall: %s.
config.cache_test_succeeded=D'éirigh leis an tástáil taisce, fuair sé freagra i %s.
config.session_config=Cumraíocht Seisiúin
config.session_provider=Soláthraí Seisiúin
config.provider_config=Cumraíocht Soláthraí
config.cookie_name=Ainm Fianán
config.gc_interval_time=Am Eatramh GC
config.session_life_time=Am Saoil na Seisiúin
config.https_only=HTTPS Amháin
config.cookie_life_time=Am Saoil Fianán
config.picture_config=Cumraíocht Pictiúr agus Avatar
config.picture_service=Seirbhís Pictiúr
config.disable_gravatar=Díchumasaigh Gravatar
config.enable_federated_avatar=Cumasaigh Avatars Cónaidhme
config.open_with_editor_app_help=Na heagarthóirí "Oscailte le" don roghchlár Clón. Má fhágtar folamh é, úsáidfear an réamhshocrú. Leathnaigh chun an réamhshocrú a fheiceáil.
config.git_config=Cumraíocht Git
config.git_disable_diff_highlight=Díchumasaigh Aibhsiú Comhréire Diff
config.git_max_diff_lines=Max Diff Lines (do chomhad amháin)
config.git_max_diff_line_characters=Carachtair Max Diff (le haghaidh líne amháin)
config.git_max_diff_files=Comhaid Max Diff (le taispeáint)
config.git_gc_args=Argóintí GC
config.git_migrate_timeout=Teorainn Ama Imirce
config.git_mirror_timeout=Teorainn Ama Nuashonraithe Scátháin
config.git_clone_timeout=Teorainn Ama Oibríochta Clón
config.git_pull_timeout=Tarraing Am Oibríochta
config.git_gc_timeout=Teorainn Ama Oibriúcháin GC
config.log_config=Cumraíocht Logáil
config.logger_name_fmt=Logálaí: %s
config.disabled_logger=Díchumasaithe
config.access_log_mode=Mód Logáil Rochtana
config.access_log_template=Teimpléad Logáil Rochtana
config.xorm_log_sql=Logáil SQL
config.set_setting_failed=Theip ar shocrú %s a shocrú
monitor.stats=Staitisticí
monitor.cron=Tascanna Cron
monitor.name=Ainm
monitor.schedule=Sceideal
monitor.next=An chéad uair eile
monitor.previous=Am Roimhe Seo
monitor.execute_times=Forghníomhaíochtaí
monitor.process=Próisis reatha
monitor.stacktrace=Rian cruachta
monitor.processes_count=Próisis %d
monitor.download_diagnosis_report=Íoslódáil tuairisc diagnóis
monitor.desc=Cur síos
monitor.start=Am Tosaigh
monitor.execute_time=Am Forghníomhaithe
monitor.last_execution_result=Toradh
monitor.process.cancel=Cealaigh próiseas
monitor.process.cancel_desc=Má chuirtear próiseas ar ceal d'fhéadfadh go gcaillfí sonraí
monitor.process.cancel_notices=Cealaigh: <strong>%s</strong>?
monitor.process.children=Leanaí
monitor.queues=Scuaineanna
monitor.queue=Scuaine: %s
monitor.queue.name=Ainm
monitor.queue.type=Cineál
monitor.queue.exemplar=Cineál Eiseamláire
monitor.queue.numberworkers=Líon na nOibrithe
monitor.queue.activeworkers=Oibrithe Gníomhacha
monitor.queue.maxnumberworkers=Líon Uasta na nOibrithe
monitor.queue.numberinqueue=Uimhir i scuaine
monitor.queue.review_add=Athbhreithniú / Cuir Oibrithe leis
monitor.queue.settings.title=Socruithe Linn
monitor.queue.settings.desc=Fásann linnte go dinimiciúil mar fhreagra ar a gcuid scuaine oibrithe a bhlocáil.
monitor.queue.settings.maxnumberworkers=Uaslíon na n-oibrithe
monitor.queue.settings.maxnumberworkers.placeholder=Faoi láthair %[1]d
monitor.queue.settings.maxnumberworkers.error=Caithfidh uaslíon na n-oibrithe a bheith ina uimhir
monitor.queue.settings.submit=Nuashonrú Socruithe
monitor.queue.settings.changed=Socruithe Nuashonraithe
monitor.queue.settings.remove_all_items=Bain gach
monitor.queue.settings.remove_all_items_done=Baineadh na míreanna go léir sa scuaine.
notices.system_notice_list=Fógraí Córais
notices.view_detail_header=Féach ar Sonraí Fógra
notices.operations=Oibríochtaí
notices.select_all=Roghnaigh Gach
notices.deselect_all=Díroghnaigh Gach
notices.inverse_selection=Roghnú Inbhéartha
notices.delete_selected=Scrios Roghnaithe
notices.delete_all=Scrios Gach Fógra
notices.type=Cineál
notices.type_1=Stóras
notices.type_2=Tasc
notices.desc=Cur síos
notices.op=Oibríocht.
notices.delete_success=Scriosadh na fógraí córais.
[action]
[tool]
now=anois
future=todhchaí
1s=1 soicind
1m=1 nóiméad
1h=1 uair an chloig
1d=1 lá
1w=1 seachtain
1mon=1 mhí
1y=1 bhliain
seconds=%d soicind
minutes=%d nóiméad
[dropzone]
[notification]
notifications=Fógraí
unread=Gan léamh
read=Léigh
subscriptions=Síntiúis
watching=Ag féachaint
no_subscriptions=Gan síntiúis
[gpg]
[units]
unit=Aonad
[packages]
title=Pacáistí
filter.type=Cineál
filter.type.all=Gach
filter.container.tagged=Clibeáilte
filter.container.untagged=Gan chlib
details=Sonraí
details.author=Údar
dependency.version=Leagan
alpine.repository.branches=Brainsí
alpine.repository.repositories=Stórais
conan.details.repository=Stóras
container.details.type=Cineál Íomhá
container.details.platform=Ardán
container.multi_arch=Córas Oibriúcháin / Ailtireacht
container.labels=Lipéid
container.labels.key=Eochair
container.labels.value=Luach
debian.repository=Eolas Stóras
debian.repository.components=Comhpháirteanna
debian.repository.architectures=Ailtireachtaí
npm.details.tag=Clib
owner.settings.cleanuprules.enabled=Cumasaithe
[secrets]
@ -2962,10 +3438,15 @@ alpine.repository.repositories=Stórais
runners.name=Ainm
runners.owner_type=Cineál
runners.description=Cur síos
runners.labels=Lipéid
runners.task_list.run=Rith
runners.task_list.repository=Stóras
runners.task_list.commit=Tiomantas
runners.status.active=Gníomhach
runners.version=Leagan
runners.reset_registration_token=Athshocraigh comhartha clár
runners.reset_registration_token_success=D'éirigh le hathshocrú comhartha clárúcháin an dara háit

View File

@ -63,6 +63,20 @@ func reqPackageAccess(accessMode perm.AccessMode) func(ctx *context.Context) {
ctx.Error(http.StatusUnauthorized, "reqPackageAccess", "user should have specific permission or be a site admin")
return
}
// check if scope only applies to public resources
publicOnly, err := scope.PublicOnly()
if err != nil {
ctx.Error(http.StatusForbidden, "tokenRequiresScope", "parsing public resource scope failed: "+err.Error())
return
}
if publicOnly {
if ctx.Package != nil && ctx.Package.Owner.Visibility.IsPrivate() {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public packages")
return
}
}
}
}

View File

@ -235,6 +235,62 @@ func reqPackageAccess(accessMode perm.AccessMode) func(ctx *context.APIContext)
}
}
func checkTokenPublicOnly() func(ctx *context.APIContext) {
return func(ctx *context.APIContext) {
if !ctx.PublicOnly {
return
}
requiredScopeCategories, ok := ctx.Data["requiredScopeCategories"].([]auth_model.AccessTokenScopeCategory)
if !ok || len(requiredScopeCategories) == 0 {
return
}
// public Only permission check
switch {
case auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryRepository):
if ctx.Repo.Repository != nil && ctx.Repo.Repository.IsPrivate {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public repos")
return
}
case auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryIssue):
if ctx.Repo.Repository != nil && ctx.Repo.Repository.IsPrivate {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public issues")
return
}
case auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryOrganization):
if ctx.Org.Organization != nil && ctx.Org.Organization.Visibility != api.VisibleTypePublic {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public orgs")
return
}
if ctx.ContextUser != nil && ctx.ContextUser.IsOrganization() && ctx.ContextUser.Visibility != api.VisibleTypePublic {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public orgs")
return
}
case auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryUser):
if ctx.ContextUser != nil && ctx.ContextUser.IsUser() && ctx.ContextUser.Visibility != api.VisibleTypePublic {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public users")
return
}
case auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryActivityPub):
if ctx.ContextUser != nil && ctx.ContextUser.IsUser() && ctx.ContextUser.Visibility != api.VisibleTypePublic {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public activitypub")
return
}
case auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryNotification):
if ctx.Repo.Repository != nil && ctx.Repo.Repository.IsPrivate {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public notifications")
return
}
case auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryPackage):
if ctx.Package != nil && ctx.Package.Owner.Visibility.IsPrivate() {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public packages")
return
}
}
}
}
// if a token is being used for auth, we check that it contains the required scope
// if a token is not being used, reqToken will enforce other sign in methods
func tokenRequiresScopes(requiredScopeCategories ...auth_model.AccessTokenScopeCategory) func(ctx *context.APIContext) {
@ -250,9 +306,6 @@ func tokenRequiresScopes(requiredScopeCategories ...auth_model.AccessTokenScopeC
return
}
ctx.Data["ApiTokenScopePublicRepoOnly"] = false
ctx.Data["ApiTokenScopePublicOrgOnly"] = false
// use the http method to determine the access level
requiredScopeLevel := auth_model.Read
if ctx.Req.Method == "POST" || ctx.Req.Method == "PUT" || ctx.Req.Method == "PATCH" || ctx.Req.Method == "DELETE" {
@ -261,6 +314,18 @@ func tokenRequiresScopes(requiredScopeCategories ...auth_model.AccessTokenScopeC
// get the required scope for the given access level and category
requiredScopes := auth_model.GetRequiredScopes(requiredScopeLevel, requiredScopeCategories...)
allow, err := scope.HasScope(requiredScopes...)
if err != nil {
ctx.Error(http.StatusForbidden, "tokenRequiresScope", "checking scope failed: "+err.Error())
return
}
if !allow {
ctx.Error(http.StatusForbidden, "tokenRequiresScope", fmt.Sprintf("token does not have at least one of required scope(s): %v", requiredScopes))
return
}
ctx.Data["requiredScopeCategories"] = requiredScopeCategories
// check if scope only applies to public resources
publicOnly, err := scope.PublicOnly()
@ -269,21 +334,8 @@ func tokenRequiresScopes(requiredScopeCategories ...auth_model.AccessTokenScopeC
return
}
// this context is used by the middleware in the specific route
ctx.Data["ApiTokenScopePublicRepoOnly"] = publicOnly && auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryRepository)
ctx.Data["ApiTokenScopePublicOrgOnly"] = publicOnly && auth_model.ContainsCategory(requiredScopeCategories, auth_model.AccessTokenScopeCategoryOrganization)
allow, err := scope.HasScope(requiredScopes...)
if err != nil {
ctx.Error(http.StatusForbidden, "tokenRequiresScope", "checking scope failed: "+err.Error())
return
}
if allow {
return
}
ctx.Error(http.StatusForbidden, "tokenRequiresScope", fmt.Sprintf("token does not have at least one of required scope(s): %v", requiredScopes))
// assign to true so that those searching should only filter public repositories/users/organizations
ctx.PublicOnly = publicOnly
}
}
@ -295,25 +347,6 @@ func reqToken() func(ctx *context.APIContext) {
return
}
if true == ctx.Data["IsApiToken"] {
publicRepo, pubRepoExists := ctx.Data["ApiTokenScopePublicRepoOnly"]
publicOrg, pubOrgExists := ctx.Data["ApiTokenScopePublicOrgOnly"]
if pubRepoExists && publicRepo.(bool) &&
ctx.Repo.Repository != nil && ctx.Repo.Repository.IsPrivate {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public repos")
return
}
if pubOrgExists && publicOrg.(bool) &&
ctx.Org.Organization != nil && ctx.Org.Organization.Visibility != api.VisibleTypePublic {
ctx.Error(http.StatusForbidden, "reqToken", "token scope is limited to public orgs")
return
}
return
}
if ctx.IsSigned {
return
}
@ -879,11 +912,11 @@ func Routes() *web.Router {
m.Group("/user/{username}", func() {
m.Get("", activitypub.Person)
m.Post("/inbox", activitypub.ReqHTTPSignature(), activitypub.PersonInbox)
}, context.UserAssignmentAPI())
}, context.UserAssignmentAPI(), checkTokenPublicOnly())
m.Group("/user-id/{user-id}", func() {
m.Get("", activitypub.Person)
m.Post("/inbox", activitypub.ReqHTTPSignature(), activitypub.PersonInbox)
}, context.UserIDAssignmentAPI())
}, context.UserIDAssignmentAPI(), checkTokenPublicOnly())
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryActivityPub))
}
@ -939,7 +972,7 @@ func Routes() *web.Router {
}, reqSelfOrAdmin(), reqBasicOrRevProxyAuth())
m.Get("/activities/feeds", user.ListUserActivityFeeds)
}, context.UserAssignmentAPI(), individualPermsChecker)
}, context.UserAssignmentAPI(), checkTokenPublicOnly(), individualPermsChecker)
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser))
// Users (requires user scope)
@ -957,7 +990,7 @@ func Routes() *web.Router {
m.Get("/starred", user.GetStarredRepos)
m.Get("/subscriptions", user.GetWatchedRepos)
}, context.UserAssignmentAPI())
}, context.UserAssignmentAPI(), checkTokenPublicOnly())
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser), reqToken())
// Users (requires user scope)
@ -1044,7 +1077,7 @@ func Routes() *web.Router {
m.Get("", user.IsStarring)
m.Put("", user.Star)
m.Delete("", user.Unstar)
}, repoAssignment())
}, repoAssignment(), checkTokenPublicOnly())
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository))
m.Get("/times", repo.ListMyTrackedTimes)
m.Get("/stopwatches", repo.GetStopwatches)
@ -1069,18 +1102,20 @@ func Routes() *web.Router {
m.Get("", user.CheckUserBlock)
m.Put("", user.BlockUser)
m.Delete("", user.UnblockUser)
}, context.UserAssignmentAPI())
}, context.UserAssignmentAPI(), checkTokenPublicOnly())
})
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser), reqToken())
// Repositories (requires repo scope, org scope)
m.Post("/org/{org}/repos",
// FIXME: we need org in context
tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization, auth_model.AccessTokenScopeCategoryRepository),
reqToken(),
bind(api.CreateRepoOption{}),
repo.CreateOrgRepoDeprecated)
// requires repo scope
// FIXME: Don't expose repository id outside of the system
m.Combo("/repositories/{id}", reqToken(), tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository)).Get(repo.GetByID)
// Repos (requires repo scope)
@ -1334,7 +1369,7 @@ func Routes() *web.Router {
m.Post("", bind(api.UpdateRepoAvatarOption{}), repo.UpdateAvatar)
m.Delete("", repo.DeleteAvatar)
}, reqAdmin(), reqToken())
}, repoAssignment())
}, repoAssignment(), checkTokenPublicOnly())
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository))
// Notifications (requires notifications scope)
@ -1343,7 +1378,7 @@ func Routes() *web.Router {
m.Combo("/notifications", reqToken()).
Get(notify.ListRepoNotifications).
Put(notify.ReadRepoNotifications)
}, repoAssignment())
}, repoAssignment(), checkTokenPublicOnly())
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryNotification))
// Issue (requires issue scope)
@ -1457,7 +1492,7 @@ func Routes() *web.Router {
Patch(reqToken(), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), bind(api.EditMilestoneOption{}), repo.EditMilestone).
Delete(reqToken(), reqRepoWriter(unit.TypeIssues, unit.TypePullRequests), repo.DeleteMilestone)
})
}, repoAssignment())
}, repoAssignment(), checkTokenPublicOnly())
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryIssue))
// NOTE: these are Gitea package management API - see packages.CommonRoutes and packages.DockerContainerRoutes for endpoints that implement package manager APIs
@ -1468,14 +1503,14 @@ func Routes() *web.Router {
m.Get("/files", reqToken(), packages.ListPackageFiles)
})
m.Get("/", reqToken(), packages.ListPackages)
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryPackage), context.UserAssignmentAPI(), context.PackageAssignmentAPI(), reqPackageAccess(perm.AccessModeRead))
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryPackage), context.UserAssignmentAPI(), context.PackageAssignmentAPI(), reqPackageAccess(perm.AccessModeRead), checkTokenPublicOnly())
// Organizations
m.Get("/user/orgs", reqToken(), tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser, auth_model.AccessTokenScopeCategoryOrganization), org.ListMyOrgs)
m.Group("/users/{username}/orgs", func() {
m.Get("", reqToken(), org.ListUserOrgs)
m.Get("/{org}/permissions", reqToken(), org.GetUserOrgsPermissions)
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser, auth_model.AccessTokenScopeCategoryOrganization), context.UserAssignmentAPI())
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser, auth_model.AccessTokenScopeCategoryOrganization), context.UserAssignmentAPI(), checkTokenPublicOnly())
m.Post("/orgs", tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), reqToken(), bind(api.CreateOrgOption{}), org.Create)
m.Get("/orgs", org.GetAll, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization))
m.Group("/orgs/{org}", func() {
@ -1533,7 +1568,7 @@ func Routes() *web.Router {
m.Delete("", org.UnblockUser)
})
}, reqToken(), reqOrgOwnership())
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), orgAssignment(true))
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), orgAssignment(true), checkTokenPublicOnly())
m.Group("/teams/{teamid}", func() {
m.Combo("").Get(reqToken(), org.GetTeam).
Patch(reqToken(), reqOrgOwnership(), bind(api.EditTeamOption{}), org.EditTeam).
@ -1553,7 +1588,7 @@ func Routes() *web.Router {
Get(reqToken(), org.GetTeamRepo)
})
m.Get("/activities/feeds", org.ListTeamActivityFeeds)
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), orgAssignment(false, true), reqToken(), reqTeamMembership())
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), orgAssignment(false, true), reqToken(), reqTeamMembership(), checkTokenPublicOnly())
m.Group("/admin", func() {
m.Group("/cron", func() {

View File

@ -191,7 +191,7 @@ func GetAll(ctx *context.APIContext) {
// "$ref": "#/responses/OrganizationList"
vMode := []api.VisibleType{api.VisibleTypePublic}
if ctx.IsSigned {
if ctx.IsSigned && !ctx.PublicOnly {
vMode = append(vMode, api.VisibleTypeLimited)
if ctx.Doer.IsAdmin {
vMode = append(vMode, api.VisibleTypePrivate)

View File

@ -149,7 +149,7 @@ func SearchIssues(ctx *context.APIContext) {
Actor: ctx.Doer,
}
if ctx.IsSigned {
opts.Private = true
opts.Private = !ctx.PublicOnly
opts.AllLimited = true
}
if ctx.FormString("owner") != "" {

View File

@ -129,6 +129,11 @@ func Search(ctx *context.APIContext) {
// "422":
// "$ref": "#/responses/validationError"
private := ctx.IsSigned && (ctx.FormString("private") == "" || ctx.FormBool("private"))
if ctx.PublicOnly {
private = false
}
opts := &repo_model.SearchRepoOptions{
ListOptions: utils.GetListOptions(ctx),
Actor: ctx.Doer,
@ -138,7 +143,7 @@ func Search(ctx *context.APIContext) {
TeamID: ctx.FormInt64("team_id"),
TopicOnly: ctx.FormBool("topic"),
Collaborate: optional.None[bool](),
Private: ctx.IsSigned && (ctx.FormString("private") == "" || ctx.FormBool("private")),
Private: private,
Template: optional.None[bool](),
StarredByID: ctx.FormInt64("starredBy"),
IncludeDescription: ctx.FormBool("includeDesc"),

View File

@ -9,6 +9,7 @@ import (
activities_model "code.gitea.io/gitea/models/activities"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers/api/v1/utils"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
@ -67,12 +68,17 @@ func Search(ctx *context.APIContext) {
maxResults = 1
users = []*user_model.User{user_model.NewActionsUser()}
default:
var visible []structs.VisibleType
if ctx.PublicOnly {
visible = []structs.VisibleType{structs.VisibleTypePublic}
}
users, maxResults, err = user_model.SearchUsers(ctx, &user_model.SearchUserOptions{
Actor: ctx.Doer,
Keyword: ctx.FormTrim("q"),
UID: uid,
Type: user_model.UserTypeIndividual,
SearchByEmail: true,
Visible: visible,
ListOptions: listOptions,
})
if err != nil {

View File

@ -35,9 +35,10 @@ type APIContext struct {
ContextUser *user_model.User // the user which is being visited, in most cases it differs from Doer
Repo *Repository
Org *APIOrganization
Package *Package
Repo *Repository
Org *APIOrganization
Package *Package
PublicOnly bool // Whether the request is for a public endpoint
}
func init() {

View File

@ -24,7 +24,7 @@
</h4>
<div class="ui attached guide table segment empty-repo-guide">
<div class="item">
<h3>{{ctx.Locale.Tr "repo.clone_this_repo"}} <small>{{ctx.Locale.Tr "repo.clone_helper" "http://git-scm.com/book/en/Git-Basics-Getting-a-Git-Repository"}}</small></h3>
<h3>{{ctx.Locale.Tr "repo.clone_this_repo"}} <small>{{ctx.Locale.Tr "repo.clone_helper" "http://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository"}}</small></h3>
<div class="repo-button-row">
{{if and .CanWriteCode (not .Repository.IsArchived)}}

View File

@ -75,6 +75,34 @@ func TestAPIListIssues(t *testing.T) {
}
}
func TestAPIListIssuesPublicOnly(t *testing.T) {
defer tests.PrepareTestEnv(t)()
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
owner1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo1.OwnerID})
session := loginUser(t, owner1.Name)
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadIssue)
link, _ := url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/issues", owner1.Name, repo1.Name))
link.RawQuery = url.Values{"state": {"all"}}.Encode()
req := NewRequest(t, "GET", link.String()).AddTokenAuth(token)
MakeRequest(t, req, http.StatusOK)
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
owner2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo2.OwnerID})
session = loginUser(t, owner2.Name)
token = getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadIssue)
link, _ = url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/issues", owner2.Name, repo2.Name))
link.RawQuery = url.Values{"state": {"all"}}.Encode()
req = NewRequest(t, "GET", link.String()).AddTokenAuth(token)
MakeRequest(t, req, http.StatusOK)
publicOnlyToken := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadIssue, auth_model.AccessTokenScopePublicOnly)
req = NewRequest(t, "GET", link.String()).AddTokenAuth(publicOnlyToken)
MakeRequest(t, req, http.StatusForbidden)
}
func TestAPICreateIssue(t *testing.T) {
defer tests.PrepareTestEnv(t)()
const body, title = "apiTestBody", "apiTestTitle"
@ -243,6 +271,12 @@ func TestAPISearchIssues(t *testing.T) {
DecodeJSON(t, resp, &apiIssues)
assert.Len(t, apiIssues, expectedIssueCount)
publicOnlyToken := getUserToken(t, "user1", auth_model.AccessTokenScopeReadIssue, auth_model.AccessTokenScopePublicOnly)
req = NewRequest(t, "GET", link.String()).AddTokenAuth(publicOnlyToken)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
assert.Len(t, apiIssues, 15) // 15 public issues
since := "2000-01-01T00:50:01+00:00" // 946687801
before := time.Unix(999307200, 0).Format(time.RFC3339)
query.Add("since", since)

View File

@ -28,9 +28,13 @@ func TestAPIRepoBranchesPlain(t *testing.T) {
repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
session := loginUser(t, user1.LowerName)
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
// public only token should be forbidden
publicOnlyToken := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopePublicOnly, auth_model.AccessTokenScopeWriteRepository)
link, _ := url.Parse(fmt.Sprintf("/api/v1/repos/org3/%s/branches", repo3.Name)) // a plain repo
MakeRequest(t, NewRequest(t, "GET", link.String()).AddTokenAuth(publicOnlyToken), http.StatusForbidden)
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
resp := MakeRequest(t, NewRequest(t, "GET", link.String()).AddTokenAuth(token), http.StatusOK)
bs, err := io.ReadAll(resp.Body)
assert.NoError(t, err)
@ -42,6 +46,8 @@ func TestAPIRepoBranchesPlain(t *testing.T) {
assert.EqualValues(t, "master", branches[1].Name)
link2, _ := url.Parse(fmt.Sprintf("/api/v1/repos/org3/%s/branches/test_branch", repo3.Name))
MakeRequest(t, NewRequest(t, "GET", link2.String()).AddTokenAuth(publicOnlyToken), http.StatusForbidden)
resp = MakeRequest(t, NewRequest(t, "GET", link2.String()).AddTokenAuth(token), http.StatusOK)
bs, err = io.ReadAll(resp.Body)
assert.NoError(t, err)
@ -49,6 +55,8 @@ func TestAPIRepoBranchesPlain(t *testing.T) {
assert.NoError(t, json.Unmarshal(bs, &branch))
assert.EqualValues(t, "test_branch", branch.Name)
MakeRequest(t, NewRequest(t, "POST", link.String()).AddTokenAuth(publicOnlyToken), http.StatusForbidden)
req := NewRequest(t, "POST", link.String()).AddTokenAuth(token)
req.Header.Add("Content-Type", "application/json")
req.Body = io.NopCloser(bytes.NewBufferString(`{"new_branch_name":"test_branch2", "old_branch_name": "test_branch", "old_ref_name":"refs/heads/test_branch"}`))
@ -73,6 +81,7 @@ func TestAPIRepoBranchesPlain(t *testing.T) {
link3, _ := url.Parse(fmt.Sprintf("/api/v1/repos/org3/%s/branches/test_branch2", repo3.Name))
MakeRequest(t, NewRequest(t, "DELETE", link3.String()), http.StatusNotFound)
MakeRequest(t, NewRequest(t, "DELETE", link3.String()).AddTokenAuth(publicOnlyToken), http.StatusForbidden)
MakeRequest(t, NewRequest(t, "DELETE", link3.String()).AddTokenAuth(token), http.StatusNoContent)
assert.NoError(t, err)

View File

@ -38,6 +38,19 @@ func TestAPIUserSearchLoggedIn(t *testing.T) {
assert.Contains(t, user.UserName, query)
assert.NotEmpty(t, user.Email)
}
publicToken := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadUser, auth_model.AccessTokenScopePublicOnly)
req = NewRequestf(t, "GET", "/api/v1/users/search?q=%s", query).
AddTokenAuth(publicToken)
resp = MakeRequest(t, req, http.StatusOK)
results = SearchResults{}
DecodeJSON(t, resp, &results)
assert.NotEmpty(t, results.Data)
for _, user := range results.Data {
assert.Contains(t, user.UserName, query)
assert.NotEmpty(t, user.Email)
assert.True(t, user.Visibility == "public")
}
}
func TestAPIUserSearchNotLoggedIn(t *testing.T) {

View File

@ -60,7 +60,7 @@ export function initRepoTopicBar() {
// how to test: input topic like " invalid topic " (with spaces), and select it from the list, then "Save"
const responseData = await response.json();
lastErrorToast = showErrorToast(responseData.message, {duration: 5000});
if (responseData.invalidTopics.length > 0) {
if (responseData.invalidTopics && responseData.invalidTopics.length > 0) {
const {invalidTopics} = responseData;
const topicLabels = queryElemChildren(topicDropdown, 'a.ui.label');
for (const [index, value] of topics.split(',').entries()) {