feat: add Custom Copyright Name and URL redirection#423
Conversation
skin changer fixes
Add config to enable/disable username casting to lowercase.
admin edit fix
in some vps input email is getting set as empty string.
New Theme Development & Upgrade Packages
Updated Russian lang/ru.json for MineTrax: full key parity with en.json, tightened terminology, and shorter UI-friendly copy where needed.
Update ru.json
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughAdds ChangesCopyright Settings Feature
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Admin
participant GeneralSettingForm as GeneralSetting.vue
participant Controller as GeneralSettingController
participant Settings as GeneralSettings
participant Footer as MainFooter.vue
Admin->>GeneralSettingForm: Enter copyright_name / copyright_url
GeneralSettingForm->>Controller: POST admin.setting.general.update
Controller->>Controller: Validate copyright_name, copyright_url
Controller->>Settings: Persist copyright_name, copyright_url
Settings-->>Controller: Saved
Controller-->>GeneralSettingForm: Redirect
Footer->>Settings: Read copyright_name / copyright_url
Settings-->>Footer: generalSettings values
Footer->>Footer: Render name (link if copyright_url set)
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Adds configurable copyright text and optional link support to the default theme footer, with corresponding admin settings, persistence via Spatie Laravel Settings, and feature coverage via a new admin feature test.
Changes:
- Added
copyright_nameandcopyright_urlfields toGeneralSettings(settings migration + model + controller validation/persistence). - Exposed the new fields in the Admin → General Settings UI and rendered them in the public footer (name falls back to
site_name, optional link when URL is set). - Rebuilt the default theme’s Vite assets to reflect the UI/layout changes.
Reviewed changes
Copilot reviewed 51 out of 55 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/Feature/Admin/GeneralSettingTest.php | Adds feature tests covering viewing settings, updating/clearing copyright fields, and URL validation. |
| resources/default/js/Shared/MainFooter.vue | Renders footer copyright name with optional link based on new settings. |
| resources/default/js/Pages/Admin/Setting/GeneralSetting.vue | Adds admin form inputs for copyright name and URL. |
| database/settings/2026_07_03_000000_add_copyright_fields_to_general_settings.php | Adds new Spatie settings keys for copyright name/URL. |
| app/Settings/GeneralSettings.php | Declares the new settings properties on GeneralSettings. |
| app/Http/Controllers/Admin/Settings/GeneralSettingController.php | Validates and persists the new copyright fields on update. |
| public/build/default/assets/VerifyEmail-C1GmyK4v.js | Rebuilt frontend bundle output. |
| public/build/default/assets/UserNotifications-DbaN5JQ3.js | Rebuilt frontend bundle output. |
| public/build/default/assets/TwoFactorChallenge-CsYC4xI-.js | Rebuilt frontend bundle output. |
| public/build/default/assets/ShowRecruitmentSubmission-4cDuWWaY.js | Rebuilt frontend bundle output. |
| public/build/default/assets/ShowRecruitment-B_6TKadX.js | Rebuilt frontend bundle output. |
| public/build/default/assets/ShowPost-DL4rAkJb.js | Rebuilt frontend bundle output. |
| public/build/default/assets/ShowNews-BklNsAsV.js | Rebuilt frontend bundle output. |
| public/build/default/assets/ShowDownload-B54z9tEn.js | Rebuilt frontend bundle output. |
| public/build/default/assets/ShowCustomPage-BGBbka_s.js | Rebuilt frontend bundle output. |
| public/build/default/assets/ShowCustomForm-ekog6_rV.js | Rebuilt frontend bundle output. |
| public/build/default/assets/ShowBannedPage-z3IP0ckg.js | Rebuilt frontend bundle output. |
| public/build/default/assets/Show-DfBy0FkQ.js | Rebuilt frontend bundle output. |
| public/build/default/assets/ResetPassword-DR_OrH06.js | Rebuilt frontend bundle output. |
| public/build/default/assets/ResetPassword-Bu2U0TJh2.js | Rebuilt frontend bundle output. |
| public/build/default/assets/Register-BA7LIWVl.js | Rebuilt frontend bundle output. |
| public/build/default/assets/PostRegistrationSetupUser-DgYGyXt2.js | Rebuilt frontend bundle output. |
| public/build/default/assets/Login-CF66QZug.js | Rebuilt frontend bundle output. |
| public/build/default/assets/IndexStaff-Btr1TPy-.js | Rebuilt frontend bundle output. |
| public/build/default/assets/IndexSession-D6QGZcPE.js | Rebuilt frontend bundle output. |
| public/build/default/assets/IndexRecruitmentSubmission-BTxiIw7O.js | Rebuilt frontend bundle output. |
| public/build/default/assets/IndexRecruitment-wXp14ayp.js | Rebuilt frontend bundle output. |
| public/build/default/assets/IndexPost-C-2jzH6F.js | Rebuilt frontend bundle output. |
| public/build/default/assets/IndexPoll-Cgp0wFKZ.js | Rebuilt frontend bundle output. |
| public/build/default/assets/IndexNews-uWEwoFtw.js | Rebuilt frontend bundle output. |
| public/build/default/assets/IndexDownload-CKUXEhJE.js | Rebuilt frontend bundle output. |
| public/build/default/assets/IndexCustomForm-BjczAtHQ.js | Rebuilt frontend bundle output. |
| public/build/default/assets/Index-DPrLEHaJ.js | Rebuilt frontend bundle output. |
| public/build/default/assets/GeneralSetting-APkzm_oO.js | Removed old built asset after rebuild/renaming. |
| public/build/default/assets/ForgotPassword-GRtIbruC.js | Rebuilt frontend bundle output. |
| public/build/default/assets/FeatureList-DeVJsV1P.js | Rebuilt frontend bundle output. |
| public/build/default/assets/DidYouKnowBox-vj4xcv5k.css | Rebuilt CSS asset output. |
| public/build/default/assets/DidYouKnowBox-B-54DjML.css | Removed old built CSS asset after rebuild/renaming. |
| public/build/default/assets/ConfirmPassword-C4Imlc0M.js | Rebuilt frontend bundle output. |
| public/build/default/assets/AppLayout-sUiMHh8S.js | Added new built asset after rebuild/renaming. |
| public/build/default/assets/AppLayout-BohlXgWD.js | Removed old built asset after rebuild/renaming. |
Files not reviewed (3)
- public/build/default/assets/AppLayout-sUiMHh8S.js: Generated file
- public/build/default/assets/DidYouKnowBox-vj4xcv5k.css: Generated file
- public/build/default/assets/GeneralSetting-Bj09Ll5Z.js: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const generalSettings = usePage().props.generalSettings; | ||
| const displayCopyrightName = generalSettings.copyright_name || generalSettings.site_name; | ||
| const copyrightUrl = generalSettings.copyright_url; |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
app/Http/Controllers/Admin/Settings/GeneralSettingController.php (1)
27-67: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoffNew validation added inline; consider Form Request class.
The new
copyright_name/copyright_urlrules extend an already large inlinevalidate()call. Per coding guidelines, controllers underapp/Http/Controllers/**should use dedicated Form Request classes with rules and custom messages rather than inline validation. This is a pre-existing pattern throughout this method, so a full conversion is a larger effort than this PR's scope, but worth tracking for a future cleanup.As per coding guidelines, "Always create Form Request classes for validation rather than inline validation in controllers; include both validation rules and custom error messages."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app/Http/Controllers/Admin/Settings/GeneralSettingController.php` around lines 27 - 67, The validation in GeneralSettingController should be moved out of the inline $request->validate() call into a dedicated Form Request class. Create a request for this settings update, move the existing rules from the controller into its rules() method, and add the custom messages there as well so the controller only handles the validated input and update flow.Source: Coding guidelines
resources/default/js/Shared/MainFooter.vue (1)
502-511: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider
target="_blank"/rel="noreferrer"for consistency with other external links.Every other external link in this file (social icons) opens in a new tab with
rel="noreferrer". The new copyright link navigates in the same tab, which is inconsistent and could unexpectedly take users away from the site.♻️ Proposed fix
<a v-if="copyrightUrl" :href="copyrightUrl" + target="_blank" + rel="noreferrer" class="hover:underline hover:text-primary" >🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@resources/default/js/Shared/MainFooter.vue` around lines 502 - 511, The copyright link in MainFooter.vue is inconsistent with the other external links in the footer, which use a new tab and noreferrer behavior. Update the anchor rendered for the copyrightUrl branch in the MainFooter component to include target="_blank" and rel="noreferrer", matching the existing social icon links while keeping the v-if/v-else display logic unchanged.resources/default/js/Pages/Admin/Setting/GeneralSetting.vue (1)
175-202: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueMinor: missing
autocompleteattribute for consistency.Sibling URL fields in this form (
discord_invite_url,youtube_url, etc.) setautocomplete="<field_name>", but the newcopyright_name/copyright_urlinputs omit it. Not functionally required, but inconsistent with the surrounding conventions.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@resources/default/js/Pages/Admin/Setting/GeneralSetting.vue` around lines 175 - 202, The new XInput fields for copyright_name and copyright_url in GeneralSetting.vue are missing the autocomplete attribute used by the other URL/text inputs in this form. Add the matching autocomplete values to both inputs, following the existing pattern in the same component (for example the sibling discord_invite_url and youtube_url fields), so the new fields stay consistent with the form conventions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@public/build/default/assets/AppLayout-sUiMHh8S.js`:
- Line 1: The copyright link validation currently allows non-web schemes, so
tighten the `copyright_url` rule in `GeneralSettingController` to accept only
`http` and `https` URLs before the value reaches `AppLayout`’s footer rendering.
Update the validation used for the general settings save flow so `copyright_url`
is restricted to web pages only, while keeping the existing `copyright_name`
behavior unchanged.
---
Nitpick comments:
In `@app/Http/Controllers/Admin/Settings/GeneralSettingController.php`:
- Around line 27-67: The validation in GeneralSettingController should be moved
out of the inline $request->validate() call into a dedicated Form Request class.
Create a request for this settings update, move the existing rules from the
controller into its rules() method, and add the custom messages there as well so
the controller only handles the validated input and update flow.
In `@resources/default/js/Pages/Admin/Setting/GeneralSetting.vue`:
- Around line 175-202: The new XInput fields for copyright_name and
copyright_url in GeneralSetting.vue are missing the autocomplete attribute used
by the other URL/text inputs in this form. Add the matching autocomplete values
to both inputs, following the existing pattern in the same component (for
example the sibling discord_invite_url and youtube_url fields), so the new
fields stay consistent with the form conventions.
In `@resources/default/js/Shared/MainFooter.vue`:
- Around line 502-511: The copyright link in MainFooter.vue is inconsistent with
the other external links in the footer, which use a new tab and noreferrer
behavior. Update the anchor rendered for the copyrightUrl branch in the
MainFooter component to include target="_blank" and rel="noreferrer", matching
the existing social icon links while keeping the v-if/v-else display logic
unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3d763207-4f25-430d-a575-15c800fdf370
📒 Files selected for processing (55)
app/Http/Controllers/Admin/Settings/GeneralSettingController.phpapp/Settings/GeneralSettings.phpdatabase/settings/2026_07_03_000000_add_copyright_fields_to_general_settings.phppublic/build/default/assets/AppLayout-BohlXgWD.jspublic/build/default/assets/AppLayout-sUiMHh8S.jspublic/build/default/assets/ChangeSkin-BsoQt9Qb.jspublic/build/default/assets/ConfirmPassword-C4Imlc0M.jspublic/build/default/assets/Dashboard-C3DZBQRW.jspublic/build/default/assets/Dev-CQf3DxpW.jspublic/build/default/assets/DidYouKnowBox-4tcv07hI.jspublic/build/default/assets/DidYouKnowBox-B-54DjML.csspublic/build/default/assets/DidYouKnowBox-vj4xcv5k.csspublic/build/default/assets/FeatureList-DeVJsV1P.jspublic/build/default/assets/ForgotPassword-GRtIbruC.jspublic/build/default/assets/GeneralSetting-APkzm_oO.jspublic/build/default/assets/GeneralSetting-Bj09Ll5Z.jspublic/build/default/assets/Index-DPrLEHaJ.jspublic/build/default/assets/IndexCustomForm-BjczAtHQ.jspublic/build/default/assets/IndexDownload-CKUXEhJE.jspublic/build/default/assets/IndexNews-uWEwoFtw.jspublic/build/default/assets/IndexPlayer-DVA9ZimN.jspublic/build/default/assets/IndexPoll-Cgp0wFKZ.jspublic/build/default/assets/IndexPost-C-2jzH6F.jspublic/build/default/assets/IndexPunishment-C51aVZyf.jspublic/build/default/assets/IndexRecruitment-wXp14ayp.jspublic/build/default/assets/IndexRecruitmentSubmission-BTxiIw7O.jspublic/build/default/assets/IndexSession-D6QGZcPE.jspublic/build/default/assets/IndexStaff-Btr1TPy-.jspublic/build/default/assets/ListLinkedPlayer-D38oU1v0.jspublic/build/default/assets/Login-CF66QZug.jspublic/build/default/assets/PostRegistrationSetupUser-DgYGyXt2.jspublic/build/default/assets/Register-BA7LIWVl.jspublic/build/default/assets/ResetPassword-Bu2U0TJh2.jspublic/build/default/assets/ResetPassword-DR_OrH06.jspublic/build/default/assets/Show-DfBy0FkQ.jspublic/build/default/assets/ShowBannedPage-z3IP0ckg.jspublic/build/default/assets/ShowCustomForm-ekog6_rV.jspublic/build/default/assets/ShowCustomPage-BGBbka_s.jspublic/build/default/assets/ShowDownload-B54z9tEn.jspublic/build/default/assets/ShowNews-BklNsAsV.jspublic/build/default/assets/ShowPlayer-DW9bY7WQ.jspublic/build/default/assets/ShowPost-DL4rAkJb.jspublic/build/default/assets/ShowPunishment-D9IuRtMU.jspublic/build/default/assets/ShowRecruitment-B_6TKadX.jspublic/build/default/assets/ShowRecruitmentSubmission-4cDuWWaY.jspublic/build/default/assets/ShowSession-_wlWpsKz.jspublic/build/default/assets/ShowUser-DaOKuWrp.jspublic/build/default/assets/TwoFactorChallenge-CsYC4xI-.jspublic/build/default/assets/UserNotifications-DbaN5JQ3.jspublic/build/default/assets/VerifyEmail-C1GmyK4v.jspublic/build/default/assets/app-kmrcdTlU.jspublic/build/default/manifest.jsonresources/default/js/Pages/Admin/Setting/GeneralSetting.vueresources/default/js/Shared/MainFooter.vuetests/Feature/Admin/GeneralSettingTest.php
💤 Files with no reviewable changes (3)
- public/build/default/assets/AppLayout-BohlXgWD.js
- public/build/default/assets/GeneralSetting-APkzm_oO.js
- public/build/default/assets/DidYouKnowBox-B-54DjML.css
| @@ -0,0 +1 @@ | |||
| import{H as e,Q as t,S as n,T as r,U as i,V as a,Wt as o,b as s,h as c,v as l,vt as u,w as d,x as f,y as p,z as m,zt as h}from"./vue.runtime.esm-bundler-BdVAZHbZ.js";import{o as g}from"./dist-B6FUfOuV.js";import{n as _,nt as v,t as y}from"./BaseLayout-Cg9j9bFk.js";import{t as b}from"./Icon-CqJy4up6.js";var ee={key:0,id:`variant_1`,class:`container flex flex-col flex-wrap px-5 py-20 mx-auto md:items-center lg:items-start md:flex-row md:flex-no-wrap`},te={class:`shrink-0 w-64 mx-auto text-center md:mx-0 md:text-left`},ne={key:0,class:`my-4 text-sm text-foreground dark:text-foreground whitespace-pre-wrap`},re={class:`mt-4`},ie={class:`inline-flex justify-center mt-2 sm:ml-auto sm:mt-0 sm:justify-start`},ae=[`href`],oe=[`href`],se=[`href`],ce=[`href`],le=[`href`],ue=[`href`],de=[`href`],fe=[`href`],pe=[`href`],me=[`href`],he=[`href`],ge=[`href`],_e=[`href`],x={class:`flex flex-col flex-wrap grow mt-10 -mb-10 text-center md:flex-row md:pl-20 md:mt-0 md:text-left`},S={class:`mb-3 font-bold text-foreground dark:text-foreground`},C={class:`mb-10 list-none`},w=[`href`],T={key:1,id:`variant_2`,class:`bg-secondary`},E={class:`mx-auto max-w-5xl px-4 py-16 sm:px-6 lg:px-8`},D={class:`flex justify-center`},O={key:0,class:`mx-auto mt-6 max-w-md text-center whitespace-pre-wrap leading-relaxed text-foreground dark:text-foreground`},k={class:`mt-12 flex flex-wrap justify-center gap-6 md:gap-8 lg:gap-12`},A=[`href`],j={class:`mt-12 flex justify-center gap-6 md:gap-8`},M={key:0},N=[`href`],P={key:1},F=[`href`],I={key:2,class:`-mt-0.5`},ve=[`href`],ye={key:3,class:`-mt-0.5`},be=[`href`],xe={key:4},Se=[`href`],L={key:5},Ce=[`href`],we={key:6},Te=[`href`],Ee={key:7},De=[`href`],Oe={key:8},ke=[`href`],Ae={key:9},je=[`href`],Me={key:10},Ne=[`href`],Pe={key:11},Fe=[`href`],Ie={key:12},Le=[`href`],Re={class:`text-sm text-foreground dark:text-foreground`},ze=[`href`],Be={key:0,class:`text-xs text-foreground`},Ve={key:0},He=[`href`],R={__name:`MainFooter`,setup(e){let s=window._customfooter,l=!!s,_=!route().current(`admin.*`)&&l,y=g().props.generalSettings,R=y.copyright_name||y.site_name,z=y.copyright_url,B=y?.discord_invite_url,V=y?.youtube_url,H=y?.facebook_url,U=y?.twitter_url,W=y?.twitch_url,G=y?.tiktok_url,K=y?.linkedin_url,q=y.threads_url,J=y.instagram_url,Y=y.whatsapp_url,X=y.telegram_url,Z=y.reddit_url,Q=y.github_url,$=[];return s?.style==`variant_1`?$=s?.columns?.filter(e=>e.items.length>0)??[]:s?.style==`variant_2`&&($=s?.columns?.reduce((e,t)=>(e.push(...t.items),e),[])),(e,l)=>{let g=i(`InertiaLink`);return m(),n(`footer`,{class:h([`w-full text-foreground bg-sidebar body-font`,{"md:mt-28":u(_)}])},[u(_)&&u(s).style==`variant_1`?(m(),n(`div`,ee,[p(`div`,te,[r(g,{class:`flex md:justify-start justify-center`,href:e.route(`home`)},{default:t(()=>[r(v,{class:`block w-auto h-9`})]),_:1},8,[`href`]),u(s).site_moto?(m(),n(`p`,ne,o(u(s).site_moto),1)):f(``,!0),p(`div`,re,[p(`span`,ie,[u(H)?(m(),n(`a`,{key:0,target:`_blank`,href:u(H),class:`text-foreground cursor-pointer hover:text-foreground dark:hover:text-foreground`},[r(b,{name:`facebook`,class:`w-5 h-5 fill-current`})],8,ae)):f(``,!0),u(U)?(m(),n(`a`,{key:1,target:`_blank`,href:u(U),class:`ml-3 text-foreground cursor-pointer hover:text-foreground dark:hover:text-foreground`},[r(b,{name:`twitter`,class:`w-5 h-5 fill-current`})],8,oe)):f(``,!0),u(K)?(m(),n(`a`,{key:2,target:`_blank`,href:u(K),class:`ml-3 -mt-0.5 text-foreground cursor-pointer hover:text-foreground dark:hover:text-foreground`},[r(b,{name:`linkedin`,class:`h-5 fill-current`})],8,se)):f(``,!0),u(V)?(m(),n(`a`,{key:3,target:`_blank`,href:u(V),class:`ml-3 -mt-0.5 text-foreground cursor-pointer hover:text-foreground dark:hover:text-foreground`},[r(b,{name:`youtube`,class:`h-6 fill-current`})],8,ce)):f(``,!0),u(B)?(m(),n(`a`,{key:4,target:`_blank`,href:u(B),class:`ml-3 -mt-0.5 text-foreground cursor-pointer hover:text-foreground dark:hover:text-foreground`},[r(b,{name:`discord`,class:`h-6 fill-current`})],8,le)):f(``,!0),u(G)?(m(),n(`a`,{key:5,target:`_blank`,href:u(G),class:`ml-3 text-foreground cursor-pointer hover:text-foreground dark:hover:text-foreground`},[r(b,{name:`tiktok`,class:`w-5 h-5 fill-current`})],8,ue)):f(``,!0),u(W)?(m(),n(`a`,{key:6,target:`_blank`,href:u(W),class:`ml-3 text-foreground cursor-pointer hover:text-foreground dark:hover:text-foreground`},[r(b,{name:`twitch`,class:`w-5 h-5 fill-current`})],8,de)):f(``,!0),u(q)?(m(),n(`a`,{key:7,target:`_blank`,href:u(q),class:`ml-3 text-foreground cursor-pointer hover:text-foreground dark:hover:text-foreground`},[r(b,{name:`threads`,class:`w-5 h-5 fill-current`})],8,fe)):f(``,!0),u(J)?(m(),n(`a`,{key:8,target:`_blank`,href:u(J),class:`ml-3 text-foreground cursor-pointer hover:text-foreground dark:hover:text-foreground`},[r(b,{name:`instagram`,class:`w-5 h-5 fill-current`})],8,pe)):f(``,!0),u(Y)?(m(),n(`a`,{key:9,target:`_blank`,href:u(Y),class:`ml-3 text-foreground cursor-pointer hover:text-foreground dark:hover:text-foreground`},[r(b,{name:`whatsapp`,class:`w-5 h-5 fill-current`})],8,me)):f(``,!0),u(X)?(m(),n(`a`,{key:10,target:`_blank`,href:u(X),class:`ml-3 text-foreground cursor-pointer hover:text-foreground dark:hover:text-foreground`},[r(b,{name:`telegram`,class:`w-5 h-5 fill-current`})],8,he)):f(``,!0),u(Z)?(m(),n(`a`,{key:11,target:`_blank`,href:u(Z),class:`ml-3 text-foreground cursor-pointer hover:text-foreground dark:hover:text-foreground`},[r(b,{name:`reddit`,class:`w-5 h-5 fill-current`})],8,ge)):f(``,!0),u(Q)?(m(),n(`a`,{key:12,target:`_blank`,href:u(Q),class:`ml-3 text-foreground cursor-pointer hover:text-foreground dark:hover:text-foreground`},[r(b,{name:`github`,class:`w-5 h-5 fill-current`})],8,_e)):f(``,!0)])])]),p(`div`,x,[(m(!0),n(c,null,a(u($),(e,t)=>(m(),n(`div`,{key:t,class:`flex-1 px-4`},[p(`h3`,S,o(e.title),1),p(`nav`,C,[(m(!0),n(c,null,a(e.items,(e,r)=>(m(),n(`li`,{key:t+`-`+r,class:`mt-3`},[p(`a`,{href:e.url,class:`text-foreground dark:text-foreground dark:hover:text-foreground cursor-pointer hover:text-foreground`},o(e.title),9,w)]))),128))])]))),128))])])):f(``,!0),u(_)&&u(s).style==`variant_2`?(m(),n(`div`,T,[p(`div`,E,[p(`div`,D,[r(g,{class:`flex md:justify-start justify-center`,href:e.route(`home`)},{default:t(()=>[r(v,{class:`block w-auto h-9`})]),_:1},8,[`href`])]),u(s).site_moto?(m(),n(`p`,O,o(u(s).site_moto),1)):f(``,!0),p(`ul`,k,[(m(!0),n(c,null,a(u($),(e,t)=>(m(),n(`li`,{key:t},[p(`a`,{class:`text-foreground transition hover:text-foreground/75 dark:text-foreground dark:hover:text-foreground/75`,href:e.url},o(e.title),9,A)]))),128))]),p(`ul`,j,[u(H)?(m(),n(`li`,M,[p(`a`,{href:u(H),rel:`noreferrer`,target:`_blank`,class:`text-foreground transition hover:text-foreground/75 dark:text-foreground dark:hover:text-foreground`},[l[0]||=p(`span`,{class:`sr-only`},`Facebook`,-1),r(b,{name:`facebook`,class:`h-6 w-6 fill-current`})],8,N)])):f(``,!0),u(U)?(m(),n(`li`,P,[p(`a`,{href:u(U),rel:`noreferrer`,target:`_blank`,class:`text-foreground transition hover:text-foreground/75 dark:text-foreground dark:hover:text-foreground`},[l[1]||=p(`span`,{class:`sr-only`},`Twitter`,-1),r(b,{name:`twitter`,class:`h-6 w-6 fill-current`})],8,F)])):f(``,!0),u(K)?(m(),n(`li`,I,[p(`a`,{href:u(K),rel:`noreferrer`,target:`_blank`,class:`text-foreground transition hover:text-foreground/75 dark:text-foreground dark:hover:text-foreground`},[l[2]||=p(`span`,{class:`sr-only`},`LinkedIn`,-1),r(b,{name:`linkedin`,class:`h-6 w-6 fill-current`})],8,ve)])):f(``,!0),u(V)?(m(),n(`li`,ye,[p(`a`,{href:u(V),rel:`noreferrer`,target:`_blank`,class:`text-foreground transition hover:text-foreground/75 dark:text-foreground dark:hover:text-foreground`},[l[3]||=p(`span`,{class:`sr-only`},`YouTube`,-1),r(b,{name:`youtube`,class:`h-7 w-7 fill-current`})],8,be)])):f(``,!0),u(B)?(m(),n(`li`,xe,[p(`a`,{href:u(B),rel:`noreferrer`,target:`_blank`,class:`text-foreground transition hover:text-foreground/75 dark:text-foreground dark:hover:text-foreground`},[l[4]||=p(`span`,{class:`sr-only`},`Discord`,-1),r(b,{name:`discord`,class:`h-6 w-6 fill-current`})],8,Se)])):f(``,!0),u(G)?(m(),n(`li`,L,[p(`a`,{href:u(G),rel:`noreferrer`,target:`_blank`,class:`text-foreground transition hover:text-foreground/75 dark:text-foreground dark:hover:text-foreground`},[l[5]||=p(`span`,{class:`sr-only`},`TikTok`,-1),r(b,{name:`tiktok`,class:`h-6 w-6 fill-current`})],8,Ce)])):f(``,!0),u(W)?(m(),n(`li`,we,[p(`a`,{href:u(W),rel:`noreferrer`,target:`_blank`,class:`text-foreground transition hover:text-foreground/75 dark:text-foreground dark:hover:text-foreground`},[l[6]||=p(`span`,{class:`sr-only`},`Twitch`,-1),r(b,{name:`twitch`,class:`h-6 w-6 fill-current`})],8,Te)])):f(``,!0),u(q)?(m(),n(`li`,Ee,[p(`a`,{href:u(q),rel:`noreferrer`,target:`_blank`,class:`text-foreground transition hover:text-foreground/75 dark:text-foreground dark:hover:text-foreground`},[l[7]||=p(`span`,{class:`sr-only`},`Threads`,-1),r(b,{name:`threads`,class:`h-6 w-6 fill-current`})],8,De)])):f(``,!0),u(J)?(m(),n(`li`,Oe,[p(`a`,{href:u(J),rel:`noreferrer`,target:`_blank`,class:`text-foreground transition hover:text-foreground/75 dark:text-foreground dark:hover:text-foreground`},[l[8]||=p(`span`,{class:`sr-only`},`Instagram`,-1),r(b,{name:`instagram`,class:`h-6 w-6 fill-current`})],8,ke)])):f(``,!0),u(Y)?(m(),n(`li`,Ae,[p(`a`,{href:u(Y),rel:`noreferrer`,target:`_blank`,class:`text-foreground transition hover:text-foreground/75 dark:text-foreground dark:hover:text-foreground`},[l[9]||=p(`span`,{class:`sr-only`},`WhatsApp`,-1),r(b,{name:`whatsapp`,class:`h-6 w-6 fill-current`})],8,je)])):f(``,!0),u(X)?(m(),n(`li`,Me,[p(`a`,{href:u(X),rel:`noreferrer`,target:`_blank`,class:`text-foreground transition hover:text-foreground/75 dark:text-foreground dark:hover:text-foreground`},[l[10]||=p(`span`,{class:`sr-only`},`Telegram`,-1),r(b,{name:`telegram`,class:`h-6 w-6 fill-current`})],8,Ne)])):f(``,!0),u(Z)?(m(),n(`li`,Pe,[p(`a`,{href:u(Z),rel:`noreferrer`,target:`_blank`,class:`text-foreground transition hover:text-foreground/75 dark:text-foreground dark:hover:text-foreground`},[l[11]||=p(`span`,{class:`sr-only`},`Reddit`,-1),r(b,{name:`reddit`,class:`h-6 w-6 fill-current`})],8,Fe)])):f(``,!0),u(Q)?(m(),n(`li`,Ie,[p(`a`,{href:u(Q),rel:`noreferrer`,target:`_blank`,class:`text-foreground transition hover:text-foreground/75 dark:text-foreground dark:hover:text-foreground`},[l[12]||=p(`span`,{class:`sr-only`},`Github`,-1),r(b,{name:`github`,class:`h-6 w-6 fill-current`})],8,Le)])):f(``,!0)])])])):f(``,!0),p(`div`,{class:h([{"bg-sidebar border-t":u(_),"bg-background":!u(_)},`flex flex-col items-center justify-center p-5`])},[p(`div`,Re,[l[13]||=d(` © `,-1),u(z)?(m(),n(`a`,{key:0,href:u(z),class:`hover:underline hover:text-primary`},o(u(R)),9,ze)):(m(),n(c,{key:1},[d(o(u(R)),1)],64)),d(` `+o(new Date().getFullYear()),1)]),e.$page.props.showPoweredBy?(m(),n(`div`,Be,[d(o(e.__(`Powered with`))+` `,1),r(b,{class:`absolute inline-flex w-4 h-4 text-destructive opacity-75 animate-ping`,name:`heart-fill`}),r(b,{class:`relative inline-flex w-4 h-4 text-destructive`,name:`heart-fill`}),l[15]||=d(` by `,-1),l[16]||=p(`a`,{target:`_blank`,href:`https://minetrax.github.io`,class:`hover:underline hover:text-primary`},`MineTrax`,-1),e.$page.props.poweredByExtraName&&e.$page.props.poweredByExtraLink?(m(),n(`span`,Ve,[l[14]||=d(` & `,-1),p(`a`,{target:`_blank`,href:e.$page.props.poweredByExtraLink,class:`hover:underline hover:text-primary`},o(e.$page.props.poweredByExtraName),9,He)])):f(``,!0)])):f(``,!0)],2)],2)}}},z={key:0,class:`z-50 flex items-center h-12 font-semibold text-primary-foreground shadow-sm bg-primary`},B=[`href`],V={onmouseover:`this.stop();`,onmouseout:`this.start();`},H={__name:`HeaderBroadcastBar`,setup(e){let{generalSettings:t}=g().props,r=t?.header_broadcast_text,i=t?.header_broadcast_url,a=l(()=>!!t?.header_broadcast_text);return(e,t)=>a.value?(m(),n(`div`,z,[p(`a`,{class:`w-full mt-2 cursor-pointer`,target:`_blank`,href:u(i)},[p(`marquee`,V,o(u(r)),1)],8,B)])):f(``,!0)}},U={__name:`AppLayout`,setup(n){return(n,i)=>(m(),s(y,null,{default:t(()=>[r(_),r(H),e(n.$slots,`default`),r(R)]),_:3}))}};export{U as t}; No newline at end of file | |||
There was a problem hiding this comment.
🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Find all references to copyright_url and related general settings validation.
rg -n --hidden --no-ignore-vcs "copyright_url|generalSettings|copyright_name|site_name" .
# Inspect likely backend validation files if found by name.
fd -a -t f -i "general|setting|settings|config|footer|copyright" .Repository: MineTrax/minetrax
Length of output: 50374
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the Laravel URL validation rule implementation.
rg -n --hidden --no-ignore-vcs "function validateUrl|validateUrl\(" vendor/laravel framework app
# If present, inspect the validator source around the URL rule.
fd -a -t f "ValidatesAttributes.php" vendor | head -n 20Repository: MineTrax/minetrax
Length of output: 364
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Read the URL validation implementation and nearby helper methods.
sed -n '2725,2795p' vendor/laravel/framework/src/Illuminate/Validation/Concerns/ValidatesAttributes.php
# Also inspect any URL-related validator docs in the framework source if present.
rg -n "url validation|scheme|FILTER_VALIDATE_URL|http|https" vendor/laravel/framework/src/Illuminate/Validation -g '*.php'Repository: MineTrax/minetrax
Length of output: 2383
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect Str::isUrl implementation and any allowed-scheme handling.
rg -n --hidden --no-ignore-vcs "function isUrl|isUrl\(" vendor/laravel/framework/src/Illuminate/Support/Str.php vendor/laravel/framework/src/Illuminate -g '*.php'
# Read the relevant section if found.
sed -n '1750,1835p' vendor/laravel/framework/src/Illuminate/Support/Str.phpRepository: MineTrax/minetrax
Length of output: 3009
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Read the exact Str::isUrl implementation.
sed -n '593,660p' vendor/laravel/framework/src/Illuminate/Support/Str.phpRepository: MineTrax/minetrax
Length of output: 7207
Restrict copyright_url to http(s)
app/Http/Controllers/Admin/Settings/GeneralSettingController.php currently uses Laravel’s url rule, which accepts non-http(s) schemes. If this footer link should only point to web pages, constrain it to http/https before saving.
🧰 Tools
🪛 ESLint
[error] 1-1: 'e' is defined but never used.
(no-unused-vars)
[error] 1-1: Missing semicolon.
(semi)
[error] 1-1: Missing semicolon.
(semi)
[error] 1-1: 'e' is defined but never used.
(no-unused-vars)
[error] 1-1: 'e' is defined but never used.
(no-unused-vars)
[error] 1-1: 't' is defined but never used.
(no-unused-vars)
[error] 1-1: Missing semicolon.
(semi)
[error] 1-1: 'n' is defined but never used.
(no-unused-vars)
[error] 1-1: 'i' is defined but never used.
(no-unused-vars)
[error] 1-1: Missing semicolon.
(semi)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@public/build/default/assets/AppLayout-sUiMHh8S.js` at line 1, The copyright
link validation currently allows non-web schemes, so tighten the `copyright_url`
rule in `GeneralSettingController` to accept only `http` and `https` URLs before
the value reaches `AppLayout`’s footer rendering. Update the validation used for
the general settings save flow so `copyright_url` is restricted to web pages
only, while keeping the existing `copyright_name` behavior unchanged.
|
too much conflict, switching to develop branch directly. |
Summary by CodeRabbit
New Features
Bug Fixes