Commit graph

235 commits

Author SHA1 Message Date
Helias
87004a7266 feat(2fa): offer the in-game QR code without a master secret
Some checks failed
Sync subtrees / sync-subtrees (push) Failing after 5s
ACore CI/CD / CI - Multisite (push) Failing after 1m1s
The Security page only handed out an in-game 2FA key when TOTPMasterSecret
was configured. It doesn't have to be: with the value unset the core stores
account.totp_secret in the clear and authserver reads it back the same way,
so the site can do that too.

isConfigured() still says no when a master secret is set but unusable, since
writing a key the server can't decrypt would lock the player out of the game.
2026-08-15 19:04:25 +02:00
Yehonal
545d1ee933 fix: align Jetpack reset password limit 2026-08-15 16:30:10 +00:00
Yehonal
1db329a8be fix: cap password recommendation at 16 characters 2026-08-15 16:09:31 +00:00
Helias
afcd68c01d fix(admin): darken the surfaces dark mode was still leaving light
Swept every admin screen for visible light backgrounds, then for text that
ended up too dark once the surface behind it went dark.

Most of it was core striping list tables on the <tr> while plugins repaint
the cells, so rows are painted at row level now and the cells go
transparent. PMPro drives its whole admin UI from :root variables, so
remapping those covers all of its screens at once. myCRED tints the body
with !important from a selector as specific as ours and loads later, hence
the html prefix on that rule.

Also covers screen options and help panels, My Sites, nav tabs, the menus
and widgets accordions, Site Health and Privacy headers, the dashboard
welcome panel, the media filter bar, ACF, and the buttons, selects and row
actions plugins were forcing light.
2026-08-15 10:47:11 +02:00
Helias
9217639c51 fix: ItemRestoration error when there are no characters 2026-08-15 10:22:38 +02:00
Helias
6d694acbf1 fix(admin): make the myCRED dark mode rules actually match
The whole myCRED block in theme.css is scoped to
body.acore-dark-mode.mycred-log-page, but nothing ever set that class,
so none of it applied and the points history page kept its white card,
light thead and light alternating rows.

Add the class from admin_body_class on myCRED screens, and match tr.alt
alongside :nth-child(even), since myCRED tags its alternating rows with
a class instead of relying on parity.
2026-08-15 00:55:39 +02:00
Stefano Borzì
07a0dcc690
fix(security): don't let a fresh login reset the 2FA attempt counter (#211) 2026-08-15 00:37:44 +02:00
Stefano Borzì
e0b27c7d64
fix(admin): stop dark mode leaving light rows behind (#212) 2026-08-15 00:37:24 +02:00
Stefano Borzì
ee47a4418a
feat(security): spell out the TOTP settings and recommend FreeOTP, add QRcode (#210) 2026-08-14 21:14:06 +02:00
Yehonal
f7f411ecc1 fix(admin): authenticate SOAP status request 2026-08-13 20:32:55 +00:00
Ryan Turner
19cf6f3d3b
[9] - PDump Acore-CMS for Characters (#206)
Co-authored-by: Benjamin Jackson <38561765+heyitsbench@users.noreply.github.com>
Co-authored-by: Andrew <47818697+Nyeriah@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Stefano Borzì <stefanoborzi32@gmail.com>
2026-08-12 00:08:13 +02:00
Ryan Turner
fa8be4f6ac
[4 / 7] - Item Restoration (#201)
Co-authored-by: Andrew <47818697+Nyeriah@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Stefano Borzì <stefanoborzi32@gmail.com>
2026-08-10 23:26:39 +02:00
Ryan Turner
dba9c02d4e
[2 / 7] - Characters menu (#199) 2026-08-10 22:30:45 +02:00
Ryan Turner
d7db9e7489
[1 / 7] - Profile theming (foundation) (#198) 2026-08-10 22:28:10 +02:00
Stefano Borzì
f1ff152d6a
fix(item-restoration): send the REST nonce from the shop page (#208) 2026-08-07 23:55:03 +02:00
Andrew
5881c0003f
feat(smartstone): gift character services via tokens (#207)
## Summary

Adds optional gifting for the **name**, **faction**, **race** and
**customization** character services using the smartstone token system
in `mod-chromiecraft-smartstone` (the feature was recently renamed from
"voucher" to "token").

When a buyer enters a recipient character name on the product page, the
purchase grants a token to that account (`.smartstone token grant
<account> <type>`, run over SOAP) instead of applying the change
directly. The recipient then redeems it in-game (`.smartstone token
claim`) on the character of their choice. Leaving the field blank keeps
the existing self-service behaviour (instant apply to the selected
character), unchanged.

Token types map 1:1 to the services (from the mod's `TokenType` enum):
rename=1, faction=2, race=3, customize=4. `char-restore-delete` has no
token equivalent and is excluded.

## Config

Gated behind a new **Smartstone Token Gifting** toggle
(`acore_smartstone_enabled`) on the admin Tools page, **disabled by
default**. With it off, all the new code paths are inert, so behaviour
is identical to today unless a server is running the smartstone module
and opts in.

## Changes

- `SmartstoneService`: new `grantToken($account, $type)` SOAP helper.
- `CharChange`: optional gift field, recipient resolution (character
name to account), token grant on `payment_complete`, and gift display at
checkout / in order meta.
- `CartValidation`: validates the gift recipient (exists, not banned,
account not banned) and skips the self character-selection requirement
in gift mode. Mirrors the existing account-wide smartstone gifting
checks.
- `Opts` / `Tools` admin page: the new toggle.
- The recipient account login is stored under a hidden
`_acore_gift_account` order-item meta key so WooCommerce keeps it out of
customer order details and emails (only the character name is shown).
The same fix is applied to the existing account-wide smartstone gifting
path, which shared the key.

## Testing

- Toggle off: services behave exactly as before.
- Toggle on, gift field blank: normal self-service.
- Toggle on, recipient name entered: order line shows "Gift for:
<name>", and on checkout a token is granted to the recipient account
(verified with `.smartstone token list <account>`). Free/$0 orders also
work since WooCommerce fires `payment_complete` for zero-total carts.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 21:18:04 -03:00
Ryan Turner
34c811f1f5
[3 / 7] - Mail Return (#200)
Split from the main PR:
https://github.com/azerothcore/acore-cms/pull/197

Split by Claude

Full overhaul: confirm prompt before returning, a 6×2 grid matching the
12-item mail cap, shows the recipient's faction/class, Wowhead tooltips
+ higher-res icons, and clean empty/loaded states.

<img width="1920" height="1030" alt="image"
src="https://github.com/user-attachments/assets/e3ed47b2-582e-40ec-a218-6ddc998be498"
/>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

* **New Features**
  * Added dark mode toggle for WordPress admin dashboard

* **Improvements**
* Redesigned character ordering screen with visual enhancements and
reset order option
  * Redesigned mail return interface with sidebar character navigation
* Enhanced mail display with item quality information and improved
metadata
  * Expanded admin styling and dark mode support across all admin pages

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-05 11:35:41 -03:00
Ryan Turner
45c4ee6a96
[5 / 7] - Unstuck / Scroll of Resurrection / RAF (#202)
Split from the main PR:
https://github.com/azerothcore/acore-cms/pull/197

Split by Claude

Unstuck restyled to the new rows; Scroll of Resurrection gets
green/red/yellow status colours; RAF (recruit-a-friend) gets a CSRF
nonce + validation. Minor shared-service tidy.

<img width="1920" height="1030" alt="image"
src="https://github.com/user-attachments/assets/97b69047-870e-41bd-878d-5c52a665384a"
/>

<img width="1920" height="1030" alt="image"
src="https://github.com/user-attachments/assets/dca4c6e3-b29d-4175-a227-84e7d52a730a"
/>

Not testde the RAF page, as the changes were made by Rabbit's review.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
  * Dark mode toggle in WordPress admin bar
  * Character order reset functionality in character management
  * Item quality indicators in mail and restoration displays

* **Improvements**
* Redesigned character management UI with card-based layout, icons, and
metadata
  * Revamped mail return interface with character sidebar navigation
* Reimagined item restoration page with card grid and improved
organization
* Enhanced security with nonce validation and permission checks across
endpoints
  * Improved visual styling with expanded theme and dark mode CSS

* **Bug Fixes**
  * Module availability validation for Resurrection Scroll feature

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-05 11:34:29 -03:00
Andrew
94af2922d2
feat(smartstone): allow gifting account-wide unlocks and cap quantity at 1 (#194)
## Summary

Builds on #190 (account-wide smartstone unlocks) with two related UX
changes on the same WooCommerce flow.

### 1. Gifting (Costumes, Perks)

Lets buyers gift any account-wide smartstone product to another player
by entering a **character name** on the product page. The plugin
resolves it to that character's owning AC account and routes the SOAP
unlock there at payment time.

UX mirrors the existing item-gifting flow in `ItemSend.php` — buyers
never type an account name (AC account logins are semi-private and
unfriendly UX); they type a character name they don't need to own.

- **Every account-wide product page** renders a
`FieldElements::destCharacter` input below the 3D viewer with the label
*"Gift to a character (optional — leave blank to unlock for your own
account)"*. No per-product opt-in toggle.
- **Empty input** → buyer's own account unlocks (existing #190 behavior,
unchanged).
- **Recipient name supplied:**
- At `add_to_cart_validation`: looked up via `findOneByName`. Rejected
with a notice if the character doesn't exist, the character is banned,
or the recipient's account is banned.
- At `add_cart_item_data`: resolved to the recipient's account name and
stashed in cart_item_data as `acore_gift_account` (functional) +
`acore_gift_charname` (display).
- At `get_item_data`: cart line shows *"Gift for: \<character name\>"*
instead of *"Unlock for: Entire account"*.
- At `add_order_item_meta`: both gift fields persisted on the order
item.
- At `payment_complete`: `addAccountVanity()` is called with the gift
account instead of the buyer's.
- **Self-gift** (recipient character belongs to the buyer's own AC
account, case-insensitive compare): silently treated as a regular
self-unlock. No error notice — the gift fields are simply not stashed,
and the cart line falls back to the standard *"Unlock for: Entire
account"* display.
- **Per-character categories** (Companion=0, Pet=1, others) are
completely untouched.

### 2. Quantity cap

Every smartstone SKU is a one-shot unlock — per-character for
ACTION_TYPE_COMPANION (0) / ACTION_TYPE_PET (1), per-account for
ACTION_TYPE_COSTUME (2) / ACTION_TYPE_PERK (9). A quantity > 1 is
nonsensical: a second unlock for the same SKU on the same target is
either rejected by the mod (`LANG_MOD_SERVICE_ALREADY_UNLOCKED`) or a
silent no-op. The buyer just pays N times for the same thing.

- `woocommerce_quantity_input_args` filter: forces `min = max =
input_value = 1` on the product-page selector for any SKU starting with
`smartstone`. WC's `wc_quantity_input()` renders the field as plain text
"1" (no +/- buttons) when min == max.
- `woocommerce_cart_item_quantity` filter: returns a plain `"1"` string
for the cart-row quantity, making it non-editable after add-to-cart.

Multiple cart lines for the same SKU are still supported (e.g. gifting
the same costume to two different recipients) — the existing
`unique_key` in `add_cart_item_data` forces each add into its own line.
Using the `sold_individually` flag would block this, so it's
intentionally not used.

## Scope

- Only `src/acore-wp-plugin/src/Hooks/WooCommerce/Smartstone.php` is
touched (+104, −5).
- All repository methods used here (`findOneByName`, `findOneById`,
`getCharactersBannedRepo`, `getAccountBannedRepo`) are already used in
`CartValidation.php` and `FieldElements.php`.
- No new SOAP wrapper, no new SKU shape, no changes to the per-character
flow.

## Known limitation (deferred)

The original spec asked for an **at-add-to-cart "already unlocked"
check** for gifting, but the mod stores account-wide unlocks in
`acore_auth.smartstone_account_settings.data` as a serialized
`PlayerSettingVector` binary blob — and perks share a `settingId` slot
per class (all Druid perks → `settingId=110`), so a row-existence check
would incorrectly block buying a second Druid perk if the recipient owns
any. A proper duplicate check requires parsing the AC binary settings
format from PHP, which is out of scope here.

Current behavior on a duplicate gift: the SOAP server returns
`LANG_MOD_SERVICE_ALREADY_UNLOCKED`, `payment_complete` catches it and
writes it to the `acore_log` WooCommerce logger, and the buyer's
WooCommerce order still completes. Worth a follow-up issue.

## Test plan

### Gifting
- [ ] Account-wide product page (e.g. `smartstone_2_<costumeId>`)
renders the *"Gift to a character"* input field below the 3D viewer.
- [ ] Empty input → checkout completes as before, buyer's account gets
the unlock, cart shows *"Unlock for: Entire account"*.
- [ ] Recipient name of a character on **another** account: cart line
shows *"Gift for: \<charname\>"*; `payment_complete` fires `.smartstone
unlock account <recipient-account-login> <cat> <id> true`.
- [ ] Recipient name of a character on the **buyer's own** account:
silently behaves like empty input (no notice, no gift fields,
self-unlock path).
- [ ] Non-existent character name → *"Recipient character not found."*
notice; Add to cart fails.
- [ ] Banned character → *"Recipient character is banned."* notice; Add
to cart fails.
- [ ] Character on a banned account → *"Recipient account is banned."*
notice; Add to cart fails.
- [ ] Per-character products (`smartstone_0_*`, `smartstone_1_*`) are
unaffected — character selector still appears, validation still requires
`acore_char_sel`.
- [ ] Mixed cart (one gifted costume + one self-unlock perk + one
per-character pet) checks out cleanly and fires three distinct SOAP
commands with the right targets.

### Quantity cap
- [ ] Any smartstone product page renders quantity as plain text "1" (no
+/- buttons).
- [ ] Same product added to cart twice with different gift recipients
produces two cart lines, each locked at qty 1.
- [ ] Cart row qty for any smartstone line is non-editable text.
- [ ] Non-smartstone products' quantity selector is unaffected.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added an optional “Gift to a character” destination field for
account-wide smartstone unlocks during checkout.
* Checkout and order item details now display “Gift for” with the
recipient name when gifting; otherwise show “Unlock for: Entire
account.”

* **Bug Fixes / Improvements**
* Smartstone quantity is capped to `1`, and cart-row quantities for
smartstone items are no longer editable.
* Self-gifting is allowed, while ban checks are enforced for the
recipient when gifting.
* Account-wide unlock routing now targets the recipient’s linked account
when a destination character is provided.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-16 14:24:55 -03:00
Stefano Borzì
bb8ecb24b7
chore: add more info about deleted character, related of #185 (#193) 2026-06-08 22:45:31 +02:00
Yehonal
e48623c8c6
fix: prevent password length validation fatal (#192) 2026-06-06 12:33:23 +02:00
Andrew
c9a6a5715c
feat(smartstone): support account-wide unlocks (costumes, perks) (#190)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23 22:53:31 +02:00
Ryan Turner
62271c7d59
fix: Windows not being able to start docker properl.y (#189)
Co-authored-by: Claude <claude@anthropic.com>
2026-05-21 11:59:29 +02:00
Andrew
c682954d87
fix(unstuck): revive character before teleporting home (#187)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 10:26:50 -03:00
Ryan Turner
e80cf27d74
Convert CRLF to LF on Windows Fix, enforce LF and updated README (#183)
Co-authored-by: FlyingArowana <TheSCREWEDSoftware@users.noreply.github.com>
2026-04-01 09:25:28 +02:00
Andrew
173426e50b
fix(raf): update same-IP text based on endRAFOnSameIP setting (#182)
## Summary
- Add `end_raf_on_same_ip` setting to the RAF config defaults and admin
panel dropdown
- When `endRAFOnSameIP` is **enabled**: keep the existing warning that
RAF will be automatically removed
- When `endRAFOnSameIP` is **disabled**: show a more coherent message
matching [ChromieCraft's
wording](https://www.chromiecraft.com/en/recruit-a-friend-is-available-now/)
— _"Whilst you can recruit a friend who shares an IP address, you will
only get the teleport & XP bonuses, no rewards will be given"_
- Wrap Eluna DB queries in a try/catch so the RAF page shows a clear "No
RAF installation found" error instead of a blank page when the database
is not configured

## Test plan
- [ ] Verify the admin panel shows the new "RAF: End RAF on same IP"
dropdown under Eluna settings
- [ ] Toggle `end_raf_on_same_ip` to **Enabled** and confirm the
original warning text appears on the RAF page
- [ ] Toggle `end_raf_on_same_ip` to **Disabled** and confirm the
updated ChromieCraft-style text appears
- [ ] Disconnect or misconfigure the Eluna database and verify the RAF
page shows the friendly error message instead of a blank page

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 21:31:32 -03:00
Andrew
3203e18687
feat(mail-return): add mail return tool page (#180)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Stefano Borzì <stefanoborzi32@gmail.com>
2026-03-26 15:50:37 +01:00
Andrew
6fd89f0118
feat(resurrection-scroll): add user page and admin toggle (#181)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 10:32:07 +01:00
Stefano Borzì
4b848cb74c
feat(3d-viewer): add custom item display id (#179) 2026-02-16 22:43:22 +01:00
Helias
2e14f02297 fix: prevent to store binlogs data for more than 3 days 2025-12-08 11:03:58 +01:00
Stefano Borzì
7256d6d9a2
fix(unstuck): prevent unstuck when it is on cooldown (#176) 2025-11-29 22:48:27 +01:00
Stefano Borzì
99c81b1396
chore: start sync subscription cron event on init (#175) 2025-11-29 19:59:30 +01:00
Stefano Borzì
02d6dcc2ab
fix: remove "daily restart" text (#173) 2025-10-22 13:12:18 +02:00
Stefano Borzì
0f6c71b5d6
fix(syn-subscriptions): improve membership sync, detecting non-expired but cancelled subscriptions (#172) 2025-09-25 22:48:59 +02:00
Ryan Turner
10b84cb66d
Do not allow smartstone skus to be added to cart without character selection (#168)
Current behavior (before this PR, as my mistake and lack of knowledge)
smartstone can be added to cart without selecting a character (from the
catologue of costumes or others from the smartstone), which leads people
buying costumes and not getting them because there's no character
associated. This fixes the current issue for the current implementation
(for character unlock the service, if this get changed to account bound,
we change smartstone impelemtnation then).

This will redirect them to the page (of "add cart") and ask them to
select the character

This is hasn't be tested, and can't test it for now.

And i tried submitting this fix on the same night of invesgiating, I
couldn't update `acore-cms` within my `chormiecraft-cms` in my WSL, lack
of linux and git together maybe.

---------

Co-authored-by: Yehonal <yehonal.azeroth@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-11 18:26:28 +02:00
Stefano Borzì
cf9caeedff
feat(model-3d-viewer): show single item model (#167) 2025-09-04 20:28:13 +02:00
Stefano Borzì
5030e637a9
feat(3d-model-viewer): add more options for model viewer, support smartstone (#166) 2025-09-04 08:58:40 +02:00
Stefano Borzì
2d112ca5cf
feat: add 3d model viewer (#164) 2025-09-02 23:07:57 +02:00
Yehonal
ec2b0e7967
fix: 404 plugin files & docker logging (#163)
Plugin files were not properly loaded because the web.local container
didn't have the volume for it

NOTE: nginx now also logs into /dev/stdout directly to make sure docker
can catch its logs, also, we filter out non-error access logs
2025-08-24 10:54:12 +02:00
Helias
d365f8624a chore: minor update about sync_subscriptions.php 2025-08-16 19:45:06 +02:00
Yehonal
f429c1d0ec update bash-lib submodule 2025-07-21 09:10:25 +02:00
Yehonal
64e3d50251
chore: clarify the plugin mirrored repository is read-only (#161)
This pull request updates the `README.md` file for the `acore-wp-plugin`
repository to clarify its purpose and limitations.
2025-07-21 08:47:14 +02:00
Helias
ddd8e68941 fix: PHP compatibility 2025-07-18 16:46:58 +02:00
ADVSuite
baa570a07b
Fix/graphql handler errors (#156)
## Description of the Change

This PR introduces a static method `AcoreUtils::handle_acore_error()`
that provides unified error handling for both GraphQL and standard
WordPress requests.

## Purpose

The goal is to centralize error handling logic across the plugin and
ensure consistent behavior depending on the request context:

- **GraphQL requests**: If `GRAPHQL_HTTP_REQUEST` is defined and set to
`true`, a `UserError` exception is thrown, which is properly handled by
the GraphQL layer.
- **Standard WordPress requests**: The user is redirected to the
plugin's settings page, and an admin notice is displayed with the
provided error message.

## Benefits

- Avoids duplicated error-handling logic throughout the codebase.
- Ensures GraphQL clients receive well-structured error responses.
- Provides a better UX for admin users when issues occur in the standard
WP context.

## Technical Notes

- The `GRAPHQL_HTTP_REQUEST` constant is defined by WPGraphQL to
indicate incoming GraphQL HTTP requests.
- `wp_redirect()` is followed by `exit` to stop further execution after
redirecting.
- `esc_html()` is used to ensure safe output in the admin notice.

## Potential Improvements

- Consider integrating logging for error tracking and diagnostics.
- Optionally extend support to handle REST API requests with JSON error
responses in the future.

---------

Co-authored-by: vittorio pinti <vittorio.pinti@gmail.com>
Co-authored-by: Yehonal <yehonal.azeroth@gmail.com>
2025-07-16 08:29:27 +02:00
Yehonal
dfacdc2517
refactor: remove unused git-subrepo, replaced with git submodules (#159)
* refactor: remove unused git-subrepo integration and update README with init script instructions

* fix: correct initialization order in init script for proper execution

* fix: correct path resolution in init script for proper application setup
2025-07-15 20:24:13 +02:00
Yehonal
3b596466b7 fix: correct try_files directive in Nginx configuration for proper request handling 2025-07-13 17:28:59 +02:00
Yehonal
fc855b8231 fix: update try_files directive in Nginx configuration for improved error handling 2025-07-13 17:18:11 +02:00
Yehonal
f64a1a61a4
feat: update Docker environment variables for database configuration (#158)
* feat: update Docker environment variables for database configuration

* fix: add check for password key in user login action to prevent undefined index error

* feat: add maintenance service configuration to Docker Compose

* feat: add maintenance mode HTML page and update Docker Compose configuration for nginx

* fix: rename maintenance service to acore-cms-maintenance in Docker Compose

* feat: configure maintenance mode in nginx and update Docker Compose for acore-cms-maintenance service

* feat: add maintenance mode configuration and HTML page for nginx
2025-07-12 12:19:28 +02:00
Yehonal
fb40ae0b2e feat: add support for environment variable configuration in Docker setup 2025-07-11 11:24:00 +02:00
Yehonal
29c0fd5ddf fix: improve error handling for Docker container startup in test setup script 2025-07-10 13:37:13 +02:00