WordPress Entwickler für Programmierung Ihrer Webprojekte
WordPress Entwickler für Programmierung Ihrer Webprojekte
  • Start
  • Unser Angebot
  • Blog
  • Kontakt
Avatar (Thumbnail) zum Blogeintrag

(CPT) Posts Zugang absichern – wp_query, Userrollen & Capabilities helfen nicht unbedingt

Jedem Artikel wohnt ein Zauber inne, meint: souri | 1. Juni 2021

berechtigung capabilities Capability pre_get_posts roles Rollen wp_query

wp_query kontrollierte keine Userberechtigungen

Sogar ohne jede Berechtigung können User (veröffentlichte) Posts sehen.

Das mag einerseits logisch, andererseits nicht intuitiv klingen.

WordPress bietet bei Beiträgen/Seiten/CPT-Post nur eine Handvoll „Sichtbarkeits“-Einstellungen.

Dazu gehören Dinge wie einen Post auf privat oder veröffentlicht zu stellen.

Eine Feinabstimmung auf Userrollen oder Berechtigungen gibt es nicht. Also nicht direkt im WordPress-Core. Das muss man auf Pluginebene lösen.

Leider.

Das mal als kurzes tl;dr.

Aber warum ist dem so? Schauen wir uns den Code an:

    Inhalt auf dieser Seite:

  1. wp_query kontrollierte keine Userberechtigungen
  2. Grundsätzliches zu WP_Query::get_posts()
  3. User ohne jede Berechtigung können alle veröffentlichten Posts sehen
  4. WP_Query::get_posts() überprüft nicht direkt auf Rollen
  5. Lösung: Wie auf Capability bei wp_query überprüfen?
  6. Lösung tl;dr
  7. Bonus: Wie mache ich das zb bei Archiv-Seiten? pre_get_posts()!
  8. Links

Grundsätzliches zu WP_Query::get_posts()

Nachfolgend eine kleine Erklärung zu dieser Funktion und zur Verwechslungsgefahr.

\WP_Query::get_posts() ist zuständig, um all die übergebenen Parametern im wp_query-Aufruf abzuarbeiten.

Damit wird dann eine SQL-Query erstellt, welche für die Datenbank-Abfrage verwendet wird.

Rückgabewert sind dann die gewünschten Posts.

Exkurs¹: Die Funktion WP_Query::get_posts ist übrigens ein gutes Beispiel für schlechten Code, denn die Funktion umfasst mehr als 1.500 Zeilen Code – ohne Blöcke thematisch in andere Funktionen auszulagern.)

Exkurs²: Die Funktion WP_Query::get_posts ist nicht zu verwechseln mit get_posts(). Erstere liegt in wp-includes/class-wp-query.php, zweitere findet sich unter wp-includes/post.php .

 

Telefon+436603100000
E-Mailsouri@wp-entwickler.at
AdresseWP-Entwickler
Safenauer-Straße 62,
8230 Hartberg

User ohne jede Berechtigung können alle veröffentlichten Posts sehen

Das mag logisch klingen, dass ein User ohne jede Berechtigung gleich viel sehen kann, wie ein nicht eingeloggter User.

Nehme ich einem User also die Berechtigung weg, einen Post zu sehen, spielt das keine Rolle – was nicht ganz logisch erscheint.

Zur Veranschaulichung, hier die Übersicht vom User Role Editor Plugin – das zeigt eine User-Rolle ohne jegliche Berechtigung:

 

User Role Editor Plugin Ansicht zu einer Benutzerrolle

 

Obwohl dieser User keinerlei Berechtigung für den CPT „Heizungsmaterial“ hat, kann jeder Post von Heizungsmaterial angeschaut werden!

Warum???

 

WP_Query::get_posts() überprüft nicht direkt auf Rollen

Es gibt keine direkte Überprüfung auf die unterschiedlichen Rollen in dieser Funktion.

Die Funktion current_user_can gibt es in der Funktion WP_Query::get_posts() genau SIEBEN! mal.

Überprüft wird auf edit_others_posts , auf read_private_posts , auf edit_post und auf read_post.

edit_others_posts

Wird nur überprüft, wenn der wp_query Parameter ‚perm‘ angegeben wurde!

if ( ! empty( $q['perm'] ) && 'editable' === $q['perm'] && ! current_user_can( $edit_others_cap ) ) {

Das ist bei einer Query vom WP-Core nicht der Fall, weder auf einer normalen Seite, noch im Archiv!

read_private_posts

Wird ebenfalls nur überprüft, wenn der Parameter „perm“ angegeben wurde:

if ( ! empty( $q['perm'] ) && 'readable' === $q['perm'] && ! current_user_can( $read_private_cap ) ) {

 

edit_post

Darauf wird überprüft, wenn eine Vorschau angezeigt wird.

 if ( $post_status_obj->protected ) {  // User must have edit permissions on the draft to preview.  if ( ! current_user_can( $edit_cap, $this->posts[0]->ID ) ) {    

und

 if ( $this->is_preview && $this->posts && current_user_can( $edit_cap, $this->posts[0]->ID ) ) {

Oder wenn ein Post Status verwendet wurde, den WordPress nicht erkennt.

 // Post status is not registered, assume it's not public.  if ( ! current_user_can( $edit_cap, $this->posts[0]->ID ) ) {

 

read_post

Auf diese Fähigkeit/Capability wird überprüft, wenn der Post-Status „privat“ ist:

} elseif ( $post_status_obj->private ) {
if ( ! current_user_can( $read_cap, $this->posts[0]->ID ) ) {

 

 

Lösung: Wie auf Capability bei wp_query überprüfen?

Wird der Permission Parameter von wp_query angegeben, so kann ich auf die Capability überprüfen.

Wichtig ist also, dass bei einem wp_query Aufruf der Parameter „perm“ angegeben wird, der Codex zeigt das auch als Beispiel:

perm Parameter bei der wp_query

Es gibt hier zwei Möglichkeiten für diesen Parameter:

  • editable
  • readable

Den „readable“ Parameter gebe ich hier an, weil ich auch „private“ Posts holen möchte, die dann einer User-Rolle angezeigt wird, die die Berechtigung bekommen hat.

 

Lösung tl;dr

Will ich jetzt Posts holen, die auf öffentlich geschalten sind aber nur den Rollen anzeigen, die die nötige Berechtigung haben?

Dann muss ich in der wp_query ‚perm‚ auf ‚editable‚ setzen.

Die User-Rolle muss folgende Capability-Einstellung besitzen:

 'edit_others_posts' => true,

Somit werden veröffentlichte Posts nur jenen Usern angezeigt, welche auch die nötige Berechtigung besitzen.
Was auch heißt, dass ich die Capability „edit_others_posts“ setzen muss!

 

Bonus: Wie mache ich das zb bei Archiv-Seiten? pre_get_posts()!

Bei zb Archivseiten erzeuge ich selbst keinen wp_query Aufruf. Der „perm“ Parameter ist auch nicht gesetzt! Das muss ich selbst erledigen.

Damit diese Überprüfungen auch bei Archivseiten o.ä. funktionieren, muss ich in die Standard-WP-Query eingreifen!

Das funktioniert eh einfach über den Hook pre_get_posts().

pre_get_posts Hook zum Ändern der Permission

Links

  • https://wp-entwickler.at/?s=wp_query
  • https://developer.wordpress.org/reference/functions/current_user_can/
  • https://developer.wordpress.org/reference/classes/wp_query/get_posts/
  • https://developer.wordpress.org/reference/functions/get_posts/
  • https://developer.wordpress.org/reference/classes/wp_query/#permission-parameters
  • https://developer.wordpress.org/reference/hooks/pre_get_posts/
  • https://wp-entwickler.at/?s=pre%20get%20posts

Navigation

Start Unser Angebot Blog

Impressum & Kontakt

wp-entwickler.at wird betrieben von

  • wp-entwickler Rene Souri
  • UID: ATU60950509
  • Safenauer-Straße 62
  • 8230 Hartberg

Wir lieben WordPress und freuen uns, mit Ihnen ein Projekt entwickeln zu können!

  • Impressum
  • AGB

wp-entwickler.at ist eine indit.at Division