Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 139 additions & 24 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,9 @@
"@markdoc/markdoc": "^0.5.7",
"astro": "^7.0.0",
"sharp": "^0.35.0"
},
"allowScripts": {
"esbuild": true,
"fsevents": true
}
}
4 changes: 2 additions & 2 deletions src/content/docs/extensions-and-development/api.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ For browser calls, FOSSBilling accepts the token in any of these places:
- `CSRFToken` in form data or query parameters
- `X-CSRF-Token` request header

The token must match the `csrf_token` cookie or the session token. The bundled [JavaScript API wrapper](/extensions-and-development/javascript/) reads the cookie and adds the token automatically.
The token must match the `fossbilling_csrf` cookie or the session token. The bundled [JavaScript API wrapper](/extensions-and-development/javascript/) reads the cookie and adds the token automatically.

Use Twig helpers for theme and module templates. This way, you don't need to manually attach CSRF tokens to the requests:

Expand All @@ -66,7 +66,7 @@ Use Twig helpers for theme and module templates. This way, you don't need to man
For raw `fetch()` requests, send the token yourself:

```javascript
const token = document.cookie.match(/csrf_token=([^;]*)/)?.[1] || '';
const token = document.cookie.match(/fossbilling_csrf=([^;]*)/)?.[1] || '';

fetch('/api/client/profile/update', {
method: 'POST',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ For links that trigger API actions:
</a>
```

Session-authenticated `client` and `admin` browser API calls require CSRF protection. The [JavaScript API wrapper](/extensions-and-development/javascript/) reads the `csrf_token` cookie and sends the token automatically.
Session-authenticated `client` and `admin` browser API calls require CSRF protection. The [JavaScript API wrapper](/extensions-and-development/javascript/) reads the `fossbilling_csrf` cookie and sends the token automatically.

Use `role: 'guest'` for public actions such as login, signup, and password reset:

Expand Down
6 changes: 3 additions & 3 deletions src/content/docs/extensions-and-development/javascript.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ document.addEventListener('DOMContentLoaded', function() {

## CSRF Tokens

FOSSBilling uses a double-submit style token for browser API calls. Browser-rendered Twig pages expose `CSRFToken` and set a `csrf_token` cookie.
FOSSBilling uses a double-submit style token for browser API calls. Browser-rendered Twig pages expose `CSRFToken` and set a `fossbilling_csrf` cookie.

| Call type | CSRF requirement |
|-----------|------------------|
| `guest` API calls | Not required. |
| `client` or `admin` API calls with the browser session | Required. |
| External `client` or `admin` API calls using an API key | Not required. |

The JavaScript wrapper reads the `csrf_token` cookie and sends it automatically where applicable. You don't need to manually attach the token to form data when using the wrapper.
The JavaScript wrapper reads the `fossbilling_csrf` cookie and sends it automatically where applicable. You don't need to manually attach the token to form data when using the wrapper.

## Making Requests

Expand Down Expand Up @@ -219,7 +219,7 @@ Use manual `fetch()` only when the wrapper does not fit. For session-authenticat

```javascript
function getCsrfToken() {
const match = document.cookie.match(/csrf_token=([^;]*)/);
const match = document.cookie.match(/fossbilling_csrf=([^;]*)/);
return match ? decodeURIComponent(match[1]) : '';
}

Expand Down
6 changes: 3 additions & 3 deletions src/content/docs/index.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ description: Learn what FOSSBilling is, where to start, and how to get involved
tableOfContents: false
banner:
content: |
<strong>0.8.5 is here!</strong> Check out the
<a href="https://github.com/FOSSBilling/FOSSBilling/releases/tag/0.8.5">release notes</a>
and the <a href="/maintenance/updating/0-7-to-0-8/">0.7 → 0.8 upgrade guide</a> for details.
<strong>0.8.6 is here!</strong> Check out the
Comment thread
admdly marked this conversation as resolved.
<a href="https://github.com/FOSSBilling/FOSSBilling/releases/tag/0.8.6">release notes</a>
and <a href="/maintenance/updating/0-7-to-0-8/">0.7 → 0.8 upgrade guide</a> for details.
---

FOSSBilling (*FOSS*: Free and Open Source Software) is a billing and client management solution for hosting providers and digital service businesses.
Expand Down
29 changes: 27 additions & 2 deletions src/content/docs/maintenance/Updating/0-7-to-0-8.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,10 @@ The `DebugBar_renderHead()` Twig function has been renamed to `debug_bar_render_

### CSRF Meta Tag Removed

The `<meta name="csrf-token" content="{{ CSRFToken }}">` tag has been removed from bundled themes. CSRF tokens are now sent via cookie (`csrf_token`) and handled automatically by the JavaScript API wrapper. If your custom theme relies on the meta tag, switch to reading the cookie:
The `<meta name="csrf-token" content="{{ CSRFToken }}">` tag has been removed from bundled themes. CSRF tokens are now sent via cookie (`fossbilling_csrf` since 0.8.6, `csrf_token` before) and handled automatically by the JavaScript API wrapper. If your custom theme relies on the meta tag, switch to reading the cookie:

```javascript
const token = document.cookie.match(/csrf_token=([^;]*)/)?.[1] || '';
const token = document.cookie.match(/fossbilling_csrf=([^;]*)/)?.[1] || '';
```

Build output is written to theme/public asset directories such as `src/public/assets`, not to a tracked `frontend/build` directory.
Expand Down Expand Up @@ -516,6 +516,31 @@ Custom modules or themes that check permissions directly via `$staff->hasPermiss

Existing staff group assignments are migrated automatically, with legacy non-admin staff from the old default group assigned to the **Migrated staff** group. For untouched legacy groups, `manage_settings` is backfilled on selected core modules where access was already granted to preserve prior behavior. After updating, review staff group assignments and permissions in the admin panel. Use the `has_permission` Twig function for template checks; in PHP, use the staff service's group-aware methods instead of reading the `permissions` field directly.

## Cookie Standardization & Security Hardening (0.8.6)

### Breaking: Cookie Names

{% aside type="caution" %}
FOSSBilling cookies now use standardized `fossbilling_*` names. Existing sessions and CSRF, locale, and timezone cookies are migrated transparently, but custom themes or scripts that read the legacy cookie names (`csrf_token`, `BBLANG`, `fb_locale`, `fb_timezone`) directly will need updating.
{% /aside %}

FOSSBilling migrates existing cookies automatically during browser requests. Update any custom code that reads cookies directly:

```javascript
// Before (0.8.5 and earlier)
const token = document.cookie.match(/csrf_token=([^;]*)/)?.[1] || '';

// After (0.8.6)
const token = document.cookie.match(/fossbilling_csrf=([^;]*)/)?.[1] || '';
```

The bundled JavaScript API wrapper (`js/api.js`) already handles the new name, so themes using `API.*` or `fb_api_form`/`fb_api_link` require no change. The old names are no longer set after the upgrade.

### Security

- **CSV exports** (clients, invoices, orders) now strip secret columns and require both `view` and `export` permissions. Staff with only `export` will no longer see full records - review group permissions if exports appear empty.
- **Extension permissions:** `manage_extensions` is now enforced for inactive modules. Staff without that permission can no longer open their configuration pages.

## Deprecations & Removals (Summary)

| Component | Status | Notes |
Expand Down
Loading