Skip to content

fix(linkedin-page): list pages for Content Admins, not only Super Admins - #1808

Open
giladresisi wants to merge 3 commits into
mainfrom
fix/linkedin-page-content-admin
Open

fix(linkedin-page): list pages for Content Admins, not only Super Admins#1808
giladresisi wants to merge 3 commits into
mainfrom
fix/linkedin-page-content-admin

Conversation

@giladresisi

Copy link
Copy Markdown
Collaborator

What kind of change does this PR introduce?

Bug fix

Why was this change needed?

A user reported that a LinkedIn page they have Content Admin access to never appears in the page-selection list when connecting a LinkedIn Page channel.

The companies() call in the LinkedIn Page provider queried organizationalEntityAcls with role=ADMINISTRATOR, so only pages where the user is a Super Admin were returned. Per LinkedIn's docs (https://learn.microsoft.com/en-us/linkedin/marketing/community-management/organizations/organization-access-control-by-role?view=li-lms-2026-07), the CONTENT_ADMINISTRATOR role also has "access to create and manage Page content, including updates", so Content Admins can post but couldn't connect their page.

The query now fetches approved ACLs (state=APPROVED) with the role projected, and keeps pages where the user's role is ADMINISTRATOR or CONTENT_ADMINISTRATOR — the two roles LinkedIn documents as allowed to post page updates. The returned shape is unchanged, so the picker, fetchPageInformation, and existing connected channels are unaffected.

Other information:

Publishing authorization is still enforced by LinkedIn at post time; this filter only controls which pages are offered in the picker.

Checklist:

Put a "X" in the boxes below to indicate you have followed the checklist;

  • I have read the CONTRIBUTING guide.
  • I have signed the Contributor License Agreement (CLA) (ICLA for individuals, CCLA for entities).
  • I confirm I have not used AI to submit this PR or generate code for it.
  • I checked that there were no similar issues or PRs already open for this.
  • This PR fixes just ONE issue

giladresisi and others added 3 commits July 28, 2026 19:19
What it validates: a top-level moov box exists in the uploaded mp4.
ISO/IEC 14496-12 (the ISO base media file format underlying mp4,
publicly available at
https://standards.iso.org/ittf/PubliclyAvailableStandards/ - see the
Movie Box definition, section 8.2.1: 'exactly one MovieBox shall be
present') makes moov mandatory: it is the index holding every track's
codec config and sample tables, and no player or platform can decode a
single frame without it. Encoders write moov last (or rewrite the file
with moov first for faststart), so a file grabbed before the encoder
finished has only ftyp + free + mdat-with-size-0 and is permanently
unplayable.

That is exactly the observed customer issue this addresses: an API
automation uploaded renders before the generator finished, Postiz
stored them (black tiles in the media gallery, since the <video>
preview cannot decode them either), and the posts failed days later at
publish time with Pinterest's 'The file is corrupted and cannot be
uploaded'. Two such production files showed the identical unfinalized
signature; a successfully published one had a proper moov. The check
walks top-level boxes only (a handful of size-field hops, no byte
scanning, handles 64-bit largesize), so cost is negligible.

What it does NOT validate: that the file is decodable. A structurally
complete mp4 with a corrupt or empty video track still passes; catching
that class needs ffprobe-level demuxing. It also does not cover the
hosted web-UI upload path, which goes browser -> R2 via Uppy S3
multipart, so the server never sees the bytes; covered here are the
paths automation uses (public API /upload and /upload-from-url, the
agent upload tool, and the XHR/self-hosted routes through the
validation pipe). That asymmetry matches the failure mode: a human
uploads a file that finished rendering and immediately sees a black
preview if not, while automation races the encoder and uploads
mid-encode - which is why this only ever surfaced via API/MCP.

Verified e2e on a local run: public API /upload returns 201 for a
valid mp4 and 400 for a moov-less one; the MCP uploadFromUrlTool
uploads a known-good production file and returns the graceful error
for the customer's actual corrupt file.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A size==1 box carries its real size in a 64-bit largesize field, so
its header is 16 bytes and any largesize under 16 is malformed; the
generic size<8 guard let 8-15 through, misaligning the box walk on
crafted input.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The organizationalEntityAcls query filtered on role=ADMINISTRATOR, so users
with the CONTENT_ADMINISTRATOR role never saw their pages when connecting a
LinkedIn Page channel, even though Content Admins can post on behalf of a
page. Fetch approved ACLs with the role projected and accept both roles.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@postiz-contribution postiz-contribution Bot added the contribution:approved Approved contributor label Jul 30, 2026
@postiz-agent

postiz-agent Bot commented Jul 30, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contribution:approved Approved contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant