diff --git a/modules/templates/helper.go b/modules/templates/helper.go index 6077938447..a884de113a 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -12,6 +12,7 @@ import ( "strings" "time" + "code.gitcaddy.com/server/v3/modules/ai" "code.gitcaddy.com/server/v3/modules/base" "code.gitcaddy.com/server/v3/modules/htmlutil" "code.gitcaddy.com/server/v3/modules/markup" @@ -165,9 +166,23 @@ func NewFuncMap() template.FuncMap { "FilenameIsImage": filenameIsImage, "TabSizeClass": tabSizeClass, + + // ----------------------------------------------------------------- + // AI features + "IsAIEnabled": ai.IsEnabled, + "IsAICodeReviewEnabled": isAICodeReviewEnabled, + "IsAIIssueTriageEnabled": isAIIssueTriageEnabled, } } +func isAICodeReviewEnabled() bool { + return ai.IsEnabled() && setting.AI.EnableCodeReview +} + +func isAIIssueTriageEnabled() bool { + return ai.IsEnabled() && setting.AI.EnableIssueTriage +} + // SanitizeHTML sanitizes the input by default sanitization rules. func SanitizeHTML(s string) template.HTML { return markup.Sanitize(s) diff --git a/options/locale/locale_cs-CZ.json b/options/locale/locale_cs-CZ.json index 2130de93d1..702eba103b 100644 --- a/options/locale/locale_cs-CZ.json +++ b/options/locale/locale_cs-CZ.json @@ -4052,5 +4052,14 @@ "admin.plugins.license_grace": "Grace Period", "admin.plugins.license_invalid": "Invalid", "admin.plugins.license_not_required": "Free", - "admin.plugins.none": "No plugins loaded" + "admin.plugins.none": "No plugins loaded", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_de-DE.json b/options/locale/locale_de-DE.json index b29b4cb107..f355005227 100644 --- a/options/locale/locale_de-DE.json +++ b/options/locale/locale_de-DE.json @@ -4251,5 +4251,14 @@ "vault.max_secrets": "Max. Geheimnisse", "vault.max_versions": "Max. Versionen", "vault.audit_retention": "Audit-Aufbewahrung", - "vault.unlimited": "Unbegrenzt" + "vault.unlimited": "Unbegrenzt", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_el-GR.json b/options/locale/locale_el-GR.json index b3d7e4f718..a81c4e4c48 100644 --- a/options/locale/locale_el-GR.json +++ b/options/locale/locale_el-GR.json @@ -3745,5 +3745,14 @@ "admin.plugins.license_grace": "Grace Period", "admin.plugins.license_invalid": "Invalid", "admin.plugins.license_not_required": "Free", - "admin.plugins.none": "No plugins loaded" + "admin.plugins.none": "No plugins loaded", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_en-US.json b/options/locale/locale_en-US.json index e521f26af2..c638d1d5ca 100644 --- a/options/locale/locale_en-US.json +++ b/options/locale/locale_en-US.json @@ -2823,6 +2823,12 @@ "org.settings.confirm_delete_account": "Confirm Deletion", "org.settings.delete_failed": "Deleting organization failed due to an internal error", "org.settings.delete_successful": "Organization %s has been deleted successfully.", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", "org.settings.homepage_pinning": "Homepage Visibility", "org.settings.pin_to_homepage": "Pin this organization to the homepage", "org.settings.pin_to_homepage_help": "When enabled, this organization will be featured on the public homepage. Only administrators can change this setting.", @@ -3917,6 +3923,9 @@ "repo.settings.license_file_error": "License saved but failed to create LICENSE.md file. You may need to create it manually.", "repo.settings.current_license": "Current License", "repo.settings.view_license_file": "View LICENSE.md file", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository.", "api": "API", "admin.config.api_header_url": "API Header Link", "admin.config.api_header_url_placeholder": "https://example.com/api/docs", diff --git a/options/locale/locale_es-ES.json b/options/locale/locale_es-ES.json index c88c1e1516..1863b2a717 100644 --- a/options/locale/locale_es-ES.json +++ b/options/locale/locale_es-ES.json @@ -3843,5 +3843,14 @@ "vault.max_secrets": "Máx. secretos", "vault.max_versions": "Máx. versiones", "vault.audit_retention": "Retención de auditoría", - "vault.unlimited": "Ilimitado" + "vault.unlimited": "Ilimitado", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_fa-IR.json b/options/locale/locale_fa-IR.json index d0e900d5d7..ef25ca12b8 100644 --- a/options/locale/locale_fa-IR.json +++ b/options/locale/locale_fa-IR.json @@ -2976,5 +2976,14 @@ "admin.plugins.license_grace": "Grace Period", "admin.plugins.license_invalid": "Invalid", "admin.plugins.license_not_required": "Free", - "admin.plugins.none": "No plugins loaded" + "admin.plugins.none": "No plugins loaded", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_fi-FI.json b/options/locale/locale_fi-FI.json index 239a467c9f..53c63a4e65 100644 --- a/options/locale/locale_fi-FI.json +++ b/options/locale/locale_fi-FI.json @@ -2243,5 +2243,14 @@ "admin.plugins.license_grace": "Grace Period", "admin.plugins.license_invalid": "Invalid", "admin.plugins.license_not_required": "Free", - "admin.plugins.none": "No plugins loaded" + "admin.plugins.none": "No plugins loaded", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_fr-FR.json b/options/locale/locale_fr-FR.json index 2362a63727..fb6843d965 100644 --- a/options/locale/locale_fr-FR.json +++ b/options/locale/locale_fr-FR.json @@ -4189,5 +4189,14 @@ "vault.max_secrets": "Max. secrets", "vault.max_versions": "Max. versions", "vault.audit_retention": "Rétention d'audit", - "vault.unlimited": "Illimité" + "vault.unlimited": "Illimité", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_ga-IE.json b/options/locale/locale_ga-IE.json index e40581c24e..2813c52163 100644 --- a/options/locale/locale_ga-IE.json +++ b/options/locale/locale_ga-IE.json @@ -4125,5 +4125,14 @@ "admin.plugins.license_grace": "Grace Period", "admin.plugins.license_invalid": "Invalid", "admin.plugins.license_not_required": "Free", - "admin.plugins.none": "No plugins loaded" + "admin.plugins.none": "No plugins loaded", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_hi-IN.json b/options/locale/locale_hi-IN.json index be0f1334fa..76e676e0d1 100644 --- a/options/locale/locale_hi-IN.json +++ b/options/locale/locale_hi-IN.json @@ -4250,5 +4250,14 @@ "vault.max_secrets": "Max Secrets", "vault.max_versions": "Max Versions", "vault.audit_retention": "Audit Retention", - "vault.unlimited": "Unlimited" + "vault.unlimited": "Unlimited", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_hu-HU.json b/options/locale/locale_hu-HU.json index 3c623a8181..a36bfc1233 100644 --- a/options/locale/locale_hu-HU.json +++ b/options/locale/locale_hu-HU.json @@ -2160,5 +2160,14 @@ "admin.plugins.license_grace": "Grace Period", "admin.plugins.license_invalid": "Invalid", "admin.plugins.license_not_required": "Free", - "admin.plugins.none": "No plugins loaded" + "admin.plugins.none": "No plugins loaded", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_id-ID.json b/options/locale/locale_id-ID.json index cba95b5d2b..7cfd2d59f0 100644 --- a/options/locale/locale_id-ID.json +++ b/options/locale/locale_id-ID.json @@ -1984,5 +1984,14 @@ "admin.plugins.license_grace": "Grace Period", "admin.plugins.license_invalid": "Invalid", "admin.plugins.license_not_required": "Free", - "admin.plugins.none": "No plugins loaded" + "admin.plugins.none": "No plugins loaded", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_is-IS.json b/options/locale/locale_is-IS.json index 34e84e1299..005952e17d 100644 --- a/options/locale/locale_is-IS.json +++ b/options/locale/locale_is-IS.json @@ -1872,5 +1872,14 @@ "admin.plugins.license_grace": "Grace Period", "admin.plugins.license_invalid": "Invalid", "admin.plugins.license_not_required": "Free", - "admin.plugins.none": "No plugins loaded" + "admin.plugins.none": "No plugins loaded", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_it-IT.json b/options/locale/locale_it-IT.json index b8f3af42e0..3a7656b5c9 100644 --- a/options/locale/locale_it-IT.json +++ b/options/locale/locale_it-IT.json @@ -3289,5 +3289,14 @@ "vault.max_secrets": "Max. segreti", "vault.max_versions": "Max. versioni", "vault.audit_retention": "Conservazione audit", - "vault.unlimited": "Illimitato" + "vault.unlimited": "Illimitato", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_ja-JP.json b/options/locale/locale_ja-JP.json index 20eb3ad778..08ba7ccf92 100644 --- a/options/locale/locale_ja-JP.json +++ b/options/locale/locale_ja-JP.json @@ -4232,5 +4232,14 @@ "vault.max_secrets": "最大シークレット数", "vault.max_versions": "最大バージョン数", "vault.audit_retention": "監査保持期間", - "vault.unlimited": "無制限" + "vault.unlimited": "無制限", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_ko-KR.json b/options/locale/locale_ko-KR.json index 8f531adcf5..df166aac78 100644 --- a/options/locale/locale_ko-KR.json +++ b/options/locale/locale_ko-KR.json @@ -2247,5 +2247,14 @@ "vault.max_secrets": "최대 시크릿", "vault.max_versions": "최대 버전", "vault.audit_retention": "감사 보존", - "vault.unlimited": "무제한" + "vault.unlimited": "무제한", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_lv-LV.json b/options/locale/locale_lv-LV.json index 4b1a26a8a5..b8101facbe 100644 --- a/options/locale/locale_lv-LV.json +++ b/options/locale/locale_lv-LV.json @@ -3766,5 +3766,14 @@ "admin.plugins.license_grace": "Grace Period", "admin.plugins.license_invalid": "Invalid", "admin.plugins.license_not_required": "Free", - "admin.plugins.none": "No plugins loaded" + "admin.plugins.none": "No plugins loaded", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_nl-NL.json b/options/locale/locale_nl-NL.json index 55fa93e1d6..72092353ce 100644 --- a/options/locale/locale_nl-NL.json +++ b/options/locale/locale_nl-NL.json @@ -2914,5 +2914,14 @@ "admin.plugins.license_grace": "Grace Period", "admin.plugins.license_invalid": "Invalid", "admin.plugins.license_not_required": "Free", - "admin.plugins.none": "No plugins loaded" + "admin.plugins.none": "No plugins loaded", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_pl-PL.json b/options/locale/locale_pl-PL.json index 8b4efab62a..3b3f92289a 100644 --- a/options/locale/locale_pl-PL.json +++ b/options/locale/locale_pl-PL.json @@ -2885,5 +2885,14 @@ "admin.plugins.license_grace": "Grace Period", "admin.plugins.license_invalid": "Invalid", "admin.plugins.license_not_required": "Free", - "admin.plugins.none": "No plugins loaded" + "admin.plugins.none": "No plugins loaded", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_pt-BR.json b/options/locale/locale_pt-BR.json index c2cd3a7911..c0b79cd1eb 100644 --- a/options/locale/locale_pt-BR.json +++ b/options/locale/locale_pt-BR.json @@ -4030,5 +4030,14 @@ "vault.max_secrets": "Máx. segredos", "vault.max_versions": "Máx. versões", "vault.audit_retention": "Retenção de auditoria", - "vault.unlimited": "Ilimitado" + "vault.unlimited": "Ilimitado", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_pt-PT.json b/options/locale/locale_pt-PT.json index 26069aaaa8..535f51b16b 100644 --- a/options/locale/locale_pt-PT.json +++ b/options/locale/locale_pt-PT.json @@ -4126,5 +4126,14 @@ "admin.plugins.license_grace": "Grace Period", "admin.plugins.license_invalid": "Invalid", "admin.plugins.license_not_required": "Free", - "admin.plugins.none": "No plugins loaded" + "admin.plugins.none": "No plugins loaded", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_ru-RU.json b/options/locale/locale_ru-RU.json index 0ca645654f..f06dd79945 100644 --- a/options/locale/locale_ru-RU.json +++ b/options/locale/locale_ru-RU.json @@ -3839,5 +3839,14 @@ "vault.max_secrets": "Макс. секретов", "vault.max_versions": "Макс. версий", "vault.audit_retention": "Хранение аудита", - "vault.unlimited": "Неограниченно" + "vault.unlimited": "Неограниченно", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_si-LK.json b/options/locale/locale_si-LK.json index 436636c8f6..98e432bcea 100644 --- a/options/locale/locale_si-LK.json +++ b/options/locale/locale_si-LK.json @@ -2931,5 +2931,14 @@ "admin.plugins.license_grace": "Grace Period", "admin.plugins.license_invalid": "Invalid", "admin.plugins.license_not_required": "Free", - "admin.plugins.none": "No plugins loaded" + "admin.plugins.none": "No plugins loaded", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_sk-SK.json b/options/locale/locale_sk-SK.json index 9b4b8c3afa..e8783c6853 100644 --- a/options/locale/locale_sk-SK.json +++ b/options/locale/locale_sk-SK.json @@ -1956,5 +1956,14 @@ "admin.plugins.license_grace": "Grace Period", "admin.plugins.license_invalid": "Invalid", "admin.plugins.license_not_required": "Free", - "admin.plugins.none": "No plugins loaded" + "admin.plugins.none": "No plugins loaded", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_sv-SE.json b/options/locale/locale_sv-SE.json index 1944d4b6d4..b4dfc227e0 100644 --- a/options/locale/locale_sv-SE.json +++ b/options/locale/locale_sv-SE.json @@ -2515,5 +2515,14 @@ "admin.plugins.license_grace": "Grace Period", "admin.plugins.license_invalid": "Invalid", "admin.plugins.license_not_required": "Free", - "admin.plugins.none": "No plugins loaded" + "admin.plugins.none": "No plugins loaded", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_tr-TR.json b/options/locale/locale_tr-TR.json index 22f73810cd..8e03b251ce 100644 --- a/options/locale/locale_tr-TR.json +++ b/options/locale/locale_tr-TR.json @@ -4124,5 +4124,14 @@ "admin.plugins.license_grace": "Grace Period", "admin.plugins.license_invalid": "Invalid", "admin.plugins.license_not_required": "Free", - "admin.plugins.none": "No plugins loaded" + "admin.plugins.none": "No plugins loaded", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_uk-UA.json b/options/locale/locale_uk-UA.json index ea12def622..a41b6f7b73 100644 --- a/options/locale/locale_uk-UA.json +++ b/options/locale/locale_uk-UA.json @@ -3896,5 +3896,14 @@ "admin.plugins.license_grace": "Grace Period", "admin.plugins.license_invalid": "Invalid", "admin.plugins.license_not_required": "Free", - "admin.plugins.none": "No plugins loaded" + "admin.plugins.none": "No plugins loaded", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_zh-CN.json b/options/locale/locale_zh-CN.json index 8d934d46da..4596dc5f02 100644 --- a/options/locale/locale_zh-CN.json +++ b/options/locale/locale_zh-CN.json @@ -4251,5 +4251,14 @@ "vault.max_secrets": "最大密钥数", "vault.max_versions": "最大版本数", "vault.audit_retention": "审计保留", - "vault.unlimited": "无限制" + "vault.unlimited": "无限制", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/options/locale/locale_zh-TW.json b/options/locale/locale_zh-TW.json index afda8d0131..7545d8f5cf 100644 --- a/options/locale/locale_zh-TW.json +++ b/options/locale/locale_zh-TW.json @@ -4159,5 +4159,14 @@ "vault.max_secrets": "最大密鑰數", "vault.max_versions": "最大版本數", "vault.audit_retention": "稽核保留", - "vault.unlimited": "無限制" + "vault.unlimited": "無限制", + "org.settings.license": "License", + "org.settings.license_type": "Organization License", + "org.settings.license_help": "Set a license for your organization. This will be stored in your .profile repository.", + "org.settings.license_saved": "License updated successfully.", + "org.settings.license_cleared": "License has been cleared.", + "org.settings.license_error": "Failed to update license.", + "repo.settings.license_scan": "Scan", + "repo.settings.license_detected": "License detected", + "repo.settings.license_not_found": "No license file detected in repository." } \ No newline at end of file diff --git a/routers/api/v1/repo/ai.go b/routers/api/v1/repo/ai.go index 93aef65346..24319f45c0 100644 --- a/routers/api/v1/repo/ai.go +++ b/routers/api/v1/repo/ai.go @@ -8,9 +8,10 @@ import ( issues_model "code.gitcaddy.com/server/v3/models/issues" "code.gitcaddy.com/server/v3/modules/ai" + "code.gitcaddy.com/server/v3/modules/json" "code.gitcaddy.com/server/v3/modules/setting" - "code.gitcaddy.com/server/v3/services/context" ai_service "code.gitcaddy.com/server/v3/services/ai" + "code.gitcaddy.com/server/v3/services/context" ) // AIReviewPullRequest performs an AI-powered code review on a pull request @@ -269,7 +270,7 @@ func AIExplainCode(ctx *context.APIContext) { } var req ExplainCodeRequest - if err := ctx.ShouldBindJSON(&req); err != nil { + if err := json.NewDecoder(ctx.Req.Body).Decode(&req); err != nil { ctx.JSON(http.StatusBadRequest, map[string]string{ "error": "Invalid request body", }) @@ -291,9 +292,9 @@ func AIExplainCode(ctx *context.APIContext) { type GenerateDocRequest struct { Code string `json:"code" binding:"Required"` FilePath string `json:"file_path"` - DocType string `json:"doc_type"` // function, class, module, api + DocType string `json:"doc_type"` // function, class, module, api Language string `json:"language"` - Style string `json:"style"` // jsdoc, docstring, xml, markdown + Style string `json:"style"` // jsdoc, docstring, xml, markdown } // AIGenerateDocumentation generates documentation using AI @@ -343,7 +344,7 @@ func AIGenerateDocumentation(ctx *context.APIContext) { } var req GenerateDocRequest - if err := ctx.ShouldBindJSON(&req); err != nil { + if err := json.NewDecoder(ctx.Req.Body).Decode(&req); err != nil { ctx.JSON(http.StatusBadRequest, map[string]string{ "error": "Invalid request body", }) @@ -384,12 +385,12 @@ func AIStatus(ctx *context.APIContext) { // "$ref": "#/responses/AIStatusResponse" status := map[string]any{ - "enabled": ai_service.IsEnabled(), - "code_review_enabled": setting.AI.EnableCodeReview, + "enabled": ai_service.IsEnabled(), + "code_review_enabled": setting.AI.EnableCodeReview, "issue_triage_enabled": setting.AI.EnableIssueTriage, - "doc_gen_enabled": setting.AI.EnableDocGen, + "doc_gen_enabled": setting.AI.EnableDocGen, "explain_code_enabled": setting.AI.EnableExplainCode, - "chat_enabled": setting.AI.EnableChat, + "chat_enabled": setting.AI.EnableChat, } if ai_service.IsEnabled() { diff --git a/routers/web/org/home.go b/routers/web/org/home.go index c083e4860b..9e536a3ec5 100644 --- a/routers/web/org/home.go +++ b/routers/web/org/home.go @@ -14,6 +14,7 @@ import ( "code.gitcaddy.com/server/v3/models/renderhelper" repo_model "code.gitcaddy.com/server/v3/models/repo" "code.gitcaddy.com/server/v3/modules/git" + "code.gitcaddy.com/server/v3/modules/gitrepo" "code.gitcaddy.com/server/v3/modules/log" "code.gitcaddy.com/server/v3/modules/markup/markdown" "code.gitcaddy.com/server/v3/modules/setting" @@ -224,6 +225,14 @@ func home(ctx *context.Context, viewRepositories bool) { } ctx.Data["OrgStats"] = orgStats + // Load organization license from .profile repo + profileRepo, orgLicense := getOrgProfileLicense(ctx, org) + if orgLicense != "" { + ctx.Data["OrgLicense"] = orgLicense + ctx.Data["ProfileRepoLink"] = profileRepo.Link() + ctx.Data["ProfileRepo"] = profileRepo + } + // Always show overview by default for organizations isViewOverview := !viewRepositories // Load profile readme if available @@ -385,3 +394,82 @@ func CreateProfileRepo(ctx *context.Context) { // Redirect to edit the README ctx.Redirect(repo.Link() + "/_edit/main/README.md") } + +// getOrgProfileLicense gets the license from the org's .profile repo +func getOrgProfileLicense(ctx *context.Context, org *organization.Organization) (*repo_model.Repository, string) { + profileRepo, err := repo_model.GetRepositoryByName(ctx, org.ID, ".profile") + if err != nil { + return nil, "" + } + + if profileRepo.IsEmpty { + return profileRepo, "" + } + + gitRepo, err := gitrepo.RepositoryFromRequestContextOrOpen(ctx, profileRepo) + if err != nil { + log.Error("getOrgProfileLicense: failed to open git repo: %v", err) + return profileRepo, "" + } + + commit, err := gitRepo.GetBranchCommit(profileRepo.DefaultBranch) + if err != nil { + log.Error("getOrgProfileLicense: failed to get branch commit: %v", err) + return profileRepo, "" + } + + // Check for LICENSE files + licenseFiles := []string{"LICENSE.md", "LICENSE", "LICENSE.txt", "COPYING"} + for _, filename := range licenseFiles { + entry, err := commit.GetTreeEntryByPath(filename) + if err == nil && !entry.IsDir() { + content, err := entry.Blob().GetBlobContent(10000) + if err == nil { + license := detectOrgLicenseType(content) + if license != "" { + return profileRepo, license + } + } + } + } + + return profileRepo, "" +} + +// detectOrgLicenseType tries to detect the license type from content +func detectOrgLicenseType(content string) string { + content = strings.ToLower(content) + + // Check for common license signatures + licensePatterns := map[string][]string{ + "MIT": {"mit license", "permission is hereby granted, free of charge"}, + "Apache-2.0": {"apache license", "version 2.0"}, + "GPL-3.0": {"gnu general public license", "version 3"}, + "GPL-2.0": {"gnu general public license", "version 2"}, + "BSD-3-Clause": {"redistribution and use in source and binary forms", "neither the name"}, + "BSD-2-Clause": {"redistribution and use in source and binary forms"}, + "LGPL-3.0": {"gnu lesser general public license", "version 3"}, + "LGPL-2.1": {"gnu lesser general public license", "version 2.1"}, + "MPL-2.0": {"mozilla public license", "version 2.0"}, + "AGPL-3.0": {"gnu affero general public license", "version 3"}, + "BSL-1.1": {"business source license", "change date"}, + "BSL-1.0": {"boost software license"}, + "Unlicense": {"this is free and unencumbered software", "unlicense"}, + "CC0-1.0": {"cc0 1.0 universal", "public domain"}, + "SSPL-1.0": {"server side public license"}, + } + + for license, patterns := range licensePatterns { + matchCount := 0 + for _, pattern := range patterns { + if strings.Contains(content, pattern) { + matchCount++ + } + } + if matchCount == len(patterns) { + return license + } + } + + return "" +} diff --git a/routers/web/org/setting_license.go b/routers/web/org/setting_license.go new file mode 100644 index 0000000000..ca6e449651 --- /dev/null +++ b/routers/web/org/setting_license.go @@ -0,0 +1,160 @@ +// Copyright 2024 The Gitea Authors and MarketAlly. All rights reserved. +// SPDX-License-Identifier: MIT + +package org + +import ( + "bytes" + "fmt" + "net/http" + "time" + + "code.gitcaddy.com/server/v3/models/organization" + repo_model "code.gitcaddy.com/server/v3/models/repo" + "code.gitcaddy.com/server/v3/modules/log" + repo_module "code.gitcaddy.com/server/v3/modules/repository" + "code.gitcaddy.com/server/v3/modules/templates" + repo_setting "code.gitcaddy.com/server/v3/routers/web/repo/setting" + shared_user "code.gitcaddy.com/server/v3/routers/web/shared/user" + "code.gitcaddy.com/server/v3/services/context" + repo_service "code.gitcaddy.com/server/v3/services/repository" + files_service "code.gitcaddy.com/server/v3/services/repository/files" +) + +const tplSettingsLicense templates.TplName = "org/settings/license" + +// SettingsLicense shows the organization license settings page +func SettingsLicense(ctx *context.Context) { + ctx.Data["Title"] = ctx.Tr("org.settings.license") + ctx.Data["PageIsOrgSettings"] = true + ctx.Data["PageIsOrgSettingsLicense"] = true + ctx.Data["LicenseTypes"] = repo_setting.LicenseTypes + + if _, err := shared_user.RenderUserOrgHeader(ctx); err != nil { + ctx.ServerError("RenderUserOrgHeader", err) + return + } + + // Load current license from .profile repo + profileRepo, license := getOrgProfileLicense(ctx, ctx.Org.Organization) + if license != "" { + ctx.Data["CurrentLicense"] = license + ctx.Data["ProfileRepo"] = profileRepo + } + + ctx.HTML(http.StatusOK, tplSettingsLicense) +} + +// SettingsLicensePost handles license settings form submission +func SettingsLicensePost(ctx *context.Context) { + licenseType := ctx.FormString("license_type") + org := ctx.Org.Organization + + ctx.Data["Title"] = ctx.Tr("org.settings.license") + ctx.Data["PageIsOrgSettings"] = true + ctx.Data["PageIsOrgSettingsLicense"] = true + ctx.Data["LicenseTypes"] = repo_setting.LicenseTypes + + // Get or create .profile repo + profileRepo, err := getOrCreateProfileRepo(ctx, org) + if err != nil { + ctx.ServerError("getOrCreateProfileRepo", err) + return + } + + if licenseType == "" { + // Clear license - delete LICENSE.md if it exists + ctx.Flash.Success(ctx.Tr("org.settings.license_cleared")) + ctx.Redirect(ctx.Org.OrgLink + "/settings/license") + return + } + + // Create LICENSE.md in .profile repo + if err := createOrgLicenseFile(ctx, profileRepo, licenseType); err != nil { + log.Error("Failed to create LICENSE.md: %v", err) + ctx.Flash.Error(ctx.Tr("org.settings.license_error")) + } else { + ctx.Flash.Success(ctx.Tr("org.settings.license_saved")) + } + + ctx.Redirect(ctx.Org.OrgLink + "/settings/license") +} + +// SettingsLicenseScan detects existing license in .profile repo +func SettingsLicenseScan(ctx *context.Context) { + profileRepo, license := getOrgProfileLicense(ctx, ctx.Org.Organization) + if license != "" { + ctx.JSON(http.StatusOK, map[string]any{ + "found": true, + "license": license, + "file": "LICENSE.md", + "repo": profileRepo.Name, + }) + return + } + + ctx.JSON(http.StatusOK, map[string]any{"found": false}) +} + +// getOrCreateProfileRepo gets or creates the .profile repo for an org +func getOrCreateProfileRepo(ctx *context.Context, org *organization.Organization) (*repo_model.Repository, error) { + profileRepo, err := repo_model.GetRepositoryByName(ctx, org.ID, ".profile") + if err == nil { + return profileRepo, nil + } + + if !repo_model.IsErrRepoNotExist(err) { + return nil, err + } + + // Create .profile repo + repo, err := repo_service.CreateRepository(ctx, ctx.Doer, org.AsUser(), repo_service.CreateRepoOptions{ + Name: ".profile", + Description: "Organization profile", + AutoInit: true, + Readme: "Default", + DefaultBranch: "main", + IsPrivate: false, + }) + if err != nil { + return nil, err + } + + return repo, nil +} + +// createOrgLicenseFile creates a LICENSE.md file in the profile repo +func createOrgLicenseFile(ctx *context.Context, repo *repo_model.Repository, licenseType string) error { + // Get license content from templates + licenseContent, err := repo_module.GetLicense(licenseType, &repo_module.LicenseValues{ + Owner: repo.OwnerName, + Email: ctx.Doer.Email, + Repo: repo.Name, + Year: time.Now().Format("2006"), + }) + if err != nil { + return fmt.Errorf("GetLicense: %w", err) + } + + // Create/update LICENSE.md using files service + opts := &files_service.ChangeRepoFilesOptions{ + Message: fmt.Sprintf("Add LICENSE.md (%s)", licenseType), + OldBranch: repo.DefaultBranch, + NewBranch: repo.DefaultBranch, + Files: []*files_service.ChangeRepoFile{ + { + Operation: "create", + TreePath: "LICENSE.md", + ContentReader: bytes.NewReader(licenseContent), + }, + }, + } + + _, err = files_service.ChangeRepoFiles(ctx, repo, ctx.Doer, opts) + if err != nil { + // If file already exists, try to update it instead + opts.Files[0].Operation = "update" + _, err = files_service.ChangeRepoFiles(ctx, repo, ctx.Doer, opts) + } + return err +} diff --git a/routers/web/repo/ai.go b/routers/web/repo/ai.go index 941b01a98c..318f04554c 100644 --- a/routers/web/repo/ai.go +++ b/routers/web/repo/ai.go @@ -8,9 +8,8 @@ import ( issues_model "code.gitcaddy.com/server/v3/models/issues" "code.gitcaddy.com/server/v3/modules/setting" - "code.gitcaddy.com/server/v3/modules/templates" - "code.gitcaddy.com/server/v3/services/context" ai_service "code.gitcaddy.com/server/v3/services/ai" + "code.gitcaddy.com/server/v3/services/context" ) // AIReviewPullRequest handles the AI review request for a pull request @@ -34,7 +33,7 @@ func AIReviewPullRequest(ctx *context.Context) { } if !issue.IsPull { - ctx.NotFound("Not a pull request", nil) + ctx.NotFound(nil) return } @@ -96,7 +95,7 @@ func AITriageIssue(ctx *context.Context) { func AISuggestLabels(ctx *context.Context) { if !ai_service.IsEnabled() { ctx.JSON(http.StatusServiceUnavailable, map[string]string{ - "error": ctx.Tr("repo.ai.service_unavailable"), + "error": "AI service is not available", }) return } @@ -119,25 +118,3 @@ func AISuggestLabels(ctx *context.Context) { ctx.JSON(http.StatusOK, suggestions) } - -// IsAIEnabled is a template helper to check if AI is enabled -func IsAIEnabled() bool { - return ai_service.IsEnabled() -} - -// IsAICodeReviewEnabled checks if AI code review is enabled -func IsAICodeReviewEnabled() bool { - return ai_service.IsEnabled() && setting.AI.EnableCodeReview -} - -// IsAIIssueTriageEnabled checks if AI issue triage is enabled -func IsAIIssueTriageEnabled() bool { - return ai_service.IsEnabled() && setting.AI.EnableIssueTriage -} - -func init() { - // Register template functions - templates.RegisterTemplateFunc("IsAIEnabled", IsAIEnabled) - templates.RegisterTemplateFunc("IsAICodeReviewEnabled", IsAICodeReviewEnabled) - templates.RegisterTemplateFunc("IsAIIssueTriageEnabled", IsAIIssueTriageEnabled) -} diff --git a/routers/web/repo/setting/license.go b/routers/web/repo/setting/license.go index 5512029dc2..61a7fa97bc 100644 --- a/routers/web/repo/setting/license.go +++ b/routers/web/repo/setting/license.go @@ -7,9 +7,11 @@ import ( "bytes" "fmt" "net/http" + "strings" "time" repo_model "code.gitcaddy.com/server/v3/models/repo" + "code.gitcaddy.com/server/v3/modules/gitrepo" "code.gitcaddy.com/server/v3/modules/log" repo_module "code.gitcaddy.com/server/v3/modules/repository" "code.gitcaddy.com/server/v3/modules/templates" @@ -67,7 +69,8 @@ var LicenseTypes = []LicenseCategory{ { Category: "Source-Available", Licenses: []LicenseInfo{ - {"BSL-1.0", "Business Source License", "Free to use, becomes open source later"}, + {"BSL-1.1", "Business Source License 1.1", "Commercial use restricted until change date"}, + {"BSL-1.0", "Boost Software License", "Permissive, similar to MIT"}, {"SSPL-1.0", "Server Side Public License", "Requires publishing entire service stack"}, }, }, @@ -153,3 +156,87 @@ func createLicenseFile(ctx *context.Context, repo *repo_model.Repository, licens } return err } + +// LicenseScan detects existing license files in the repository +func LicenseScan(ctx *context.Context) { + repo := ctx.Repo.Repository + + if repo.IsEmpty { + ctx.JSON(http.StatusOK, map[string]any{"found": false}) + return + } + + gitRepo, err := gitrepo.RepositoryFromRequestContextOrOpen(ctx, repo) + if err != nil { + log.Error("LicenseScan: failed to open git repo: %v", err) + ctx.JSON(http.StatusOK, map[string]any{"found": false}) + return + } + + commit, err := gitRepo.GetBranchCommit(repo.DefaultBranch) + if err != nil { + log.Error("LicenseScan: failed to get branch commit: %v", err) + ctx.JSON(http.StatusOK, map[string]any{"found": false}) + return + } + + // Check for LICENSE files + licenseFiles := []string{"LICENSE.md", "LICENSE", "LICENSE.txt", "COPYING"} + for _, filename := range licenseFiles { + entry, err := commit.GetTreeEntryByPath(filename) + if err == nil && !entry.IsDir() { + content, err := entry.Blob().GetBlobContent(10000) + if err == nil { + license := detectLicenseType(content) + if license != "" { + ctx.JSON(http.StatusOK, map[string]any{ + "found": true, + "license": license, + "file": filename, + }) + return + } + } + } + } + + ctx.JSON(http.StatusOK, map[string]any{"found": false}) +} + +// detectLicenseType tries to detect the license type from content +func detectLicenseType(content string) string { + content = strings.ToLower(content) + + // Check for common license signatures + licensePatterns := map[string][]string{ + "MIT": {"mit license", "permission is hereby granted, free of charge"}, + "Apache-2.0": {"apache license", "version 2.0"}, + "GPL-3.0": {"gnu general public license", "version 3"}, + "GPL-2.0": {"gnu general public license", "version 2"}, + "BSD-3-Clause": {"redistribution and use in source and binary forms", "neither the name"}, + "BSD-2-Clause": {"redistribution and use in source and binary forms"}, + "LGPL-3.0": {"gnu lesser general public license", "version 3"}, + "LGPL-2.1": {"gnu lesser general public license", "version 2.1"}, + "MPL-2.0": {"mozilla public license", "version 2.0"}, + "AGPL-3.0": {"gnu affero general public license", "version 3"}, + "BSL-1.1": {"business source license", "change date"}, + "BSL-1.0": {"boost software license"}, + "Unlicense": {"this is free and unencumbered software", "unlicense"}, + "CC0-1.0": {"cc0 1.0 universal", "public domain"}, + "SSPL-1.0": {"server side public license"}, + } + + for license, patterns := range licensePatterns { + matchCount := 0 + for _, pattern := range patterns { + if strings.Contains(content, pattern) { + matchCount++ + } + } + if matchCount == len(patterns) { + return license + } + } + + return "" +} diff --git a/routers/web/web.go b/routers/web/web.go index aee94f9fbe..033f3eca88 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1031,6 +1031,12 @@ func registerWebRoutes(m *web.Router) { m.Post("/initialize", web.Bind(forms.InitializeLabelsForm{}), org.InitializeLabels) }) + m.Group("/license", func() { + m.Get("", org.SettingsLicense) + m.Post("", org.SettingsLicensePost) + m.Get("/scan", org.SettingsLicenseScan) + }) + m.Group("/actions", func() { m.Get("", org_setting.RedirectToDefaultSetting) addSettingsRunnersRoutes() @@ -1158,6 +1164,7 @@ func registerWebRoutes(m *web.Router) { m.Group("/license", func() { m.Get("", repo_setting.License) m.Post("", repo_setting.LicensePost) + m.Get("/scan", repo_setting.LicenseScan) }) m.Combo("/public_access").Get(repo_setting.PublicAccess).Post(repo_setting.PublicAccessPost) diff --git a/services/ai/ai.go b/services/ai/ai.go index adf900a23f..f19095a03a 100644 --- a/services/ai/ai.go +++ b/services/ai/ai.go @@ -8,10 +8,12 @@ import ( "fmt" "strings" + "code.gitcaddy.com/server/v3/models/db" issues_model "code.gitcaddy.com/server/v3/models/issues" repo_model "code.gitcaddy.com/server/v3/models/repo" "code.gitcaddy.com/server/v3/modules/ai" "code.gitcaddy.com/server/v3/modules/git" + "code.gitcaddy.com/server/v3/modules/gitrepo" "code.gitcaddy.com/server/v3/modules/log" "code.gitcaddy.com/server/v3/modules/setting" "code.gitcaddy.com/server/v3/services/gitdiff" @@ -38,8 +40,15 @@ func ReviewPullRequest(ctx context.Context, pr *issues_model.PullRequest) (*ai.R return nil, fmt.Errorf("failed to load issue: %w", err) } + // Open git repo + gitRepo, err := gitrepo.OpenRepository(ctx, pr.BaseRepo) + if err != nil { + return nil, fmt.Errorf("failed to open git repo: %w", err) + } + defer gitRepo.Close() + // Get the diff - diff, err := gitdiff.GetDiff(ctx, pr.BaseRepo, + diff, err := gitdiff.GetDiffForAPI(ctx, gitRepo, &gitdiff.DiffOptions{ BeforeCommitID: pr.MergeBase, AfterCommitID: pr.HeadCommitID, @@ -115,7 +124,7 @@ func TriageIssue(ctx context.Context, issue *issues_model.Issue) (*ai.TriageIssu } // Get available labels - labels, err := issues_model.GetLabelsByRepoID(ctx, issue.RepoID, "", issues_model.ListOptions{}) + labels, err := issues_model.GetLabelsByRepoID(ctx, issue.RepoID, "", db.ListOptions{}) if err != nil { return nil, fmt.Errorf("failed to get labels: %w", err) } @@ -164,7 +173,7 @@ func SuggestLabels(ctx context.Context, issue *issues_model.Issue) (*ai.SuggestL } // Get available labels - labels, err := issues_model.GetLabelsByRepoID(ctx, issue.RepoID, "", issues_model.ListOptions{}) + labels, err := issues_model.GetLabelsByRepoID(ctx, issue.RepoID, "", db.ListOptions{}) if err != nil { return nil, fmt.Errorf("failed to get labels: %w", err) } diff --git a/templates/org/home.tmpl b/templates/org/home.tmpl index 35fed00c8f..b0370e5c15 100644 --- a/templates/org/home.tmpl +++ b/templates/org/home.tmpl @@ -322,6 +322,21 @@ {{end}} + {{/* Organization License - Sidebar Card */}} + {{if .OrgLicense}} +
+
+ {{svg "octicon-law" 24}} +
+
{{ctx.Locale.Tr "repo.license"}}
+ + {{.OrgLicense}} + +
+
+
+ {{end}} + {{/* Members/Public Members Section */}} {{if .IsOrganizationMember}} {{/* Internal view - show all members */}} diff --git a/templates/org/settings/license.tmpl b/templates/org/settings/license.tmpl new file mode 100644 index 0000000000..5cc69b85d0 --- /dev/null +++ b/templates/org/settings/license.tmpl @@ -0,0 +1,72 @@ +{{template "org/settings/layout_head" (dict "ctxData" . "pageClass" "organization settings license")}} + +
+

+ {{ctx.Locale.Tr "org.settings.license"}} +

+
+
+ {{.CsrfTokenHtml}} +
+ +
+ + +
+
+ {{if .CurrentLicense}} +
+ +

{{.CurrentLicense}}

+ {{if .ProfileRepo}} +

+ {{ctx.Locale.Tr "repo.settings.view_license_file"}} +

+ {{end}} +
+ {{end}} +
{{ctx.Locale.Tr "org.settings.license_help"}}
+ +
+
+
+ + + +{{template "org/settings/layout_footer" .}} diff --git a/templates/org/settings/navbar.tmpl b/templates/org/settings/navbar.tmpl index 58475de7e7..6aaffee48d 100644 --- a/templates/org/settings/navbar.tmpl +++ b/templates/org/settings/navbar.tmpl @@ -12,6 +12,9 @@ {{ctx.Locale.Tr "repo.labels"}} + + {{ctx.Locale.Tr "org.settings.license"}} + {{if .EnableOAuth2}} {{ctx.Locale.Tr "settings.applications"}} diff --git a/templates/repo/settings/license.tmpl b/templates/repo/settings/license.tmpl index 102ec98044..800d162797 100644 --- a/templates/repo/settings/license.tmpl +++ b/templates/repo/settings/license.tmpl @@ -8,16 +8,21 @@ {{.CsrfTokenHtml}}
- + + {{range .LicenseTypes}} + + {{range .Licenses}} + + {{end}} + {{end}} - - {{end}} - + + +
{{if .Repository.LicenseType}}
@@ -33,4 +38,32 @@
+ + + {{template "repo/settings/layout_footer" .}}