Role i uprawnienia WordPress: add_role, add_cap i bezpieczeństwo

Role i uprawnienia WordPress: add_role, add_cap i bezpieczeństwo

Ostatnio zweryfikowano: 13 października 2026
14 min czytania
Przewodnik
Full-stack developer
Audytor bezpieczeństwa

WordPress ma wbudowaną listę kontroli dostępu, a prawie nikt z niej nie korzysta. Najczęstszy błąd uprawnień na stronach klientów to nie niezałatana wtyczka, tylko redaktor treści z rolą Administrator, bo ktoś raz potrzebował przestawić menu. Ten przewodnik pokazuje, co API ról i uprawnień robi na poziomie źródeł: gdzie leżą dane, dlaczego add_role() milcząco ignoruje drugie wywołanie, do czego naprawdę sprowadza się sprawdzenie nazwy roli i które capabilities są szersze, niż sugeruje nazwa.

Jedna zmiana robi większość roboty. Przestań nazywać role w warunkach i nazwij capability, której kod naprawdę potrzebuje. Reszta przewodnika to koszt tej decyzji w praktyce.

#1. Rola a uprawnienie (capability) w WordPress

Capability to pojedynczy ciąg uprawnienia: edit_posts, publish_pages, install_plugins. Rola to nazwany worek tych ciągów. WordPress przechowuje worek, a ewaluuje ciąg.

Domyślne worki są mniejsze, niż się zakłada. Według dokumentacji ról i uprawnień WordPress Editor ma 26 capabilities, a Author siedem: read, upload_files, edit_posts, edit_published_posts, publish_posts, delete_posts, delete_published_posts. Contributor ma trzy: read, edit_posts, delete_posts. Contributor nie może wgrać pliku, stąd ticket o bibliotece mediów po „dajcie mu Contributor”.

Editor niesie unfiltered_html na single-site (surowy <script> w treści). W multisite map_meta_cap() odmawia go wszystkim poza super adminami:

if ( defined( 'DISALLOW_UNFILTERED_HTML' ) && DISALLOW_UNFILTERED_HTML ) {
    $caps[] = 'do_not_allow';
} elseif ( is_multisite() && ! is_super_admin( $user_id ) ) {
    $caps[] = 'do_not_allow';
} else {
    $caps[] = 'unfiltered_html';
}

Czego Editor nie ma: edit_theme_options, list_users, edit_users, manage_options, niczego związanego z wtyczkami.

#Dlaczego sprawdzenie nazwy roli wydaje się działać

Sprawdzanie nazwy roli to nie błąd składni. Jest gorzej: zwraca poprawną odpowiedź w jedynym przypadku, który przetestowałeś.

// Źle
if ( current_user_can( 'administrator' ) ) { ... }

// Dobrze
if ( current_user_can( 'manage_options' ) ) { ... }

Pierwsza linia zwraca true dla administratora przez merge na końcu WP_User::get_role_caps():

$this->allcaps = array();
foreach ( (array) $this->roles as $role ) {
    $the_role      = $wp_roles->get_role( $role );
    $this->allcaps = array_merge( (array) $this->allcaps, (array) $the_role->capabilities );
}
$this->allcaps = array_merge( (array) $this->allcaps, (array) $this->caps );

$this->caps to surowa meta wp_capabilities, a jej kluczami są nazwy ról. Stąd administrator => true ląduje w allcaps obok prawdziwych uprawnień i przechodzi sprawdzenie przypadkiem. Dokumentacja current_user_can() mówi, że sprawdzanie ról zamiast capabilities jest częściowo wspierane, ale odradzane, bo daje niepewne wyniki.

Trzy scenariusze z żywych wdrożeń:

  1. Budujesz własną rolę z manage_options, żeby klient wszedł na stronę ustawień. current_user_can('administrator') jest false. Twoja własna strona admina zwraca 403 użytkownikowi, dla którego ją zrobiłeś.
  2. Capability nadane bezpośrednio na obiekcie użytkownika, bez roli, przechodzi każde sprawdzenie capability i pada przy każdym sprawdzeniu roli.
  3. W multisite WP_User::has_cap() dla super adminów kończy się wcześniej, zanim zajrzy do allcaps, i zwraca true dla wszystkiego poza do_not_allow. Sprawdzenie roli nic tam nie rozróżnia.

Sprawdzenia capability przeżywają wszystkie trzy, bo capability to to, czego kod naprawdę potrzebuje.

#2. Jak dodać własną rolę w WordPress

Zanim napiszesz własną, sprawdź, czy platforma już ją dostarcza. WooCommerce przy instalacji dodaje shop_manager i customer. Według dokumentacji ról WooCommerce Shop Manager i tak zarządza produktami, zamówieniami, kuponami i kontami klientów. Równoległy „manager sklepu” dubluje rolę aktualizowaną w cudzym cyklu wydań.

Gdy naprawdę potrzebujesz własnej:

add_role(
    'editorial_lead',
    'Szef redakcji',
    [
        'read'                 => true,
        'upload_files'         => true,
        'edit_posts'           => true,
        'edit_others_posts'    => true,
        'edit_published_posts' => true,
        'publish_posts'        => true,
        'delete_posts'         => true,
        'moderate_comments'    => true,
    ]
);

Dwie rzeczy z tej sygnatury nie wynikają z dokumentacji API.

Zapisuje raz i potem Cię ignoruje. Handbook wtyczek mówi, że po pierwszym wywołaniu rola i capabilities są w bazie, a „kolejne wywołania nic nie robią: także przy zmianie listy uprawnień” (tłumaczenie własne). Edytujesz tablicę, wdrażasz, i nic się nie zmienia. Każda zmiana capabilities wymaga migracji:

const EDITORIAL_LEAD_VERSION = 3;

function wppoland_sync_editorial_lead() {
    if ( (int) get_option( 'wppoland_editorial_lead_version' ) === EDITORIAL_LEAD_VERSION ) {
        return;
    }

    remove_role( 'editorial_lead' );
    add_role( 'editorial_lead', 'Szef redakcji', [ /* ... */ ] );

    update_option( 'wppoland_editorial_lead_version', EDITORIAL_LEAD_VERSION );
}
register_activation_hook( __FILE__, 'wppoland_sync_editorial_lead' );
add_action( 'admin_init', 'wppoland_sync_editorial_lead' );

Kopia na admin_init ma znaczenie w multisite i przy deployach, które nie odpalają activation hooka. Bramka wersji trzyma to poza ścieżką krytyczną; handbook ostrzega, że bezwarunkowe usuwanie i ponowne dodawanie „mocno degraduje wydajność” (tłumaczenie własne).

remove_role() nie rusza użytkowników. Usuwa klucz w wierszu options. Każdy użytkownik, którego meta wp_capabilities nadal mówi editorial_lead => true, zachowuje ten klucz, WP_Roles::is_role() zwraca już dla niego false, więc nigdy nie zamienia się on w uprawnienia. Użytkownikowi zostaje ciąg, który niczego nie nadaje. Przypisz użytkowników przed usunięciem albo zaraz po.

Gdzie leży wiersz. WP_Roles::for_site() buduje klucz $wpdb->get_blog_prefix( $this->site_id ) . 'user_roles'. Na single-site z domyślnym prefiksem to wp_user_roles. Na subsite 3 sieci to wp_3_user_roles, i dlatego rola dodana na jednej podstronie sieci nie istnieje na następnej. Jeśli chcesz mieć role zdefiniowane w kodzie i nigdy niezapisywane w bazie, ustaw global $wp_user_roles w wp-config.php: WordPress używa wtedy jego, a opcja ról, jak pisze referencja core, nie jest ani aktualizowana, ani używana.

#Etykiety ról na stronach wielojęzycznych

Drugi argument add_role() to etykieta widoczna w panelu, a WP_Roles::add_role() zapisuje ją w wierszu options dokładnie w tej postaci, w jakiej przyszła. Jeśli owiniesz ją w __(), w bazie ląduje ciąg w języku aktywnym w chwili aktywacji, a nie w języku osoby, która później otwiera ekran użytkowników. Przy wyświetlaniu wp_dropdown_roles() przepuszcza etykietę przez translate_user_role(), która tłumaczy z kontekstem User role w domenie tekstowej default. To obejmuje role core, których ciągi są w katalogu WordPressa, i nie obejmuje etykiety Twojej wtyczki. Na stronie wielojęzycznej trzymaj slug i etykietę po angielsku i nie opieraj logiki na etykiecie: stabilnym identyfikatorem jest slug.

#3. Jak dodać uprawnienie do istniejącej roli

get_role() plus add_cap() to mniejszy diff, gdy domyślna rola jest prawie dobra:

$role = get_role( 'editor' );
if ( $role ) {
    $role->add_cap( 'edit_theme_options' );
}

Ta sama bramka wersji z sekcji 2 obowiązuje. WP_Role::add_cap() przyjmuje dokładnie dwa parametry, add_cap( $cap, $grant = true ), a drugi decyduje, czy uprawnienie jest nadane, czy jawnie odebrane, a nie o tym, czy wiersz zostanie zapisany. Trzeciego parametru tu nie ma. Forma trzyargumentowa należy do WP_Roles::add_cap( $role, $cap, $grant ), innej klasy, i to do tej metody deleguje WP_Role::add_cap(). Ta metoda przypisuje uprawnienie i woła update_option() zawsze, gdy use_db jest true, przy każdym wywołaniu. Żaden argument nie wyłącza zapisu, więc add_cap() na init bez bramki oznacza próbę zapisu opcji przy każdym żądaniu.

#Zakres edit_theme_options w motywach blokowych

Większy problem tej konkretnej linii to zakres. edit_theme_options to klasyczna poprawka typu „niech Editor zarządza menu” i przy motywie klasycznym robi mniej więcej to: Wygląd dla widgetów, menu, Customizera i nagłówka. Przy motywie blokowym to inne uprawnienie. Dokumentacja core nazywa je teraz głównym uprawnieniem, które WordPress sprawdza, gdy decyduje, czy użytkownik może wejść do szablonów i nimi zarządzać w Site Editorze, i ostrzega, że nie ogranicza się wyłącznie do Site Editora i może dać dostęp do innych funkcji administracyjnych związanych z motywem.

Editor, któremu chciałeś pozwolić przestawić menu, ma więc teraz Site Editor: szablony, części szablonów, style globalne i nawigację. To szerszy grant niż switch_themes, który odsłania tylko Wygląd i Wygląd > Motywy.

Jeśli naprawdę chcesz roli do Site Editora, dokumentacja wymienia, czego potrzebuje: edit_theme_options do dostępu i menu nawigacji, do tego edit_posts, edit_pages i edit_others_posts do zarządzania szablonami, read do podglądu i upload_files do mediów.

Błąd jest tu cichy, bo Site Editor rozmawia z REST API. Endpointy szablonów i części szablonów sprawdzają edit_theme_options, endpointy wpisów i stron robią własne sprawdzenia. Rola, która otwiera Site Editor, ale nie ma edit_others_posts, dostaje panel, który się ładuje, a potem nie zapisuje zmian. Zanim zaczniesz dokładać uprawnienia na ślepo, przejrzyj zakładkę sieci w poszukiwaniu odpowiedzi 401 i 403: kod błędu REST nazywa uprawnienie, którego zabrakło.

#Uprawnienia warunkowe przez user_has_cap

Niektóre reguły nie mieszczą się w roli, bo zależą od obiektu: na przykład Editor, który nie może ruszać wpisów z jednej konkretnej kategorii. Do tego służy filtr user_has_cap. WP_User::has_cap() stosuje go po map_meta_cap(), z czterema argumentami: $allcaps (co użytkownik ma), $caps (prymitywy wymagane przez sprawdzenie), $args (żądane uprawnienie w $args[0], ID użytkownika w $args[1] i zwykle ID obiektu w $args[2]) oraz obiekt WP_User.

add_filter( 'user_has_cap', function ( $allcaps, $caps, $args, $user ) {
    if ( 'edit_post' !== ( $args[0] ?? '' ) || empty( $args[2] ) ) {
        return $allcaps;
    }
    if ( has_term( 'legal', 'category', $args[2] ) && empty( $allcaps['manage_options'] ) ) {
        foreach ( $caps as $cap ) {
            $allcaps[ $cap ] = false;
        }
    }
    return $allcaps;
}, 10, 4 );

Trzy szczegóły w źródłach decydują, czy to działa. Filtr widzi tylko sprawdzenia, które niosą ID obiektu, więc current_user_can( 'edit_posts' ) przechodzi przez niego bez uruchomienia reguły. Działa przy każdym sprawdzeniu uprawnień, więc wczesny return w pierwszej linii nie jest opcjonalny. A w multisite nie dociera do super adminów: has_cap() zwraca dla nich true, zanim zastosuje filtr, co pokazuje sekcja 6.

#4. Jak zresetować role WordPress do domyślnych

Skrypt resetu z parametrem GET, który krążył też we wcześniejszych edycjach tego artykułu, to zdalne podniesienie uprawnień:

// Nie wdrażaj tego.
if ( ! isset( $_GET['reset_roles_secret_key'] ) ) return;
require_once( ABSPATH . 'wp-admin/includes/schema.php' );
populate_roles();

isset() sprawdza obecność parametru, nie poprawność. Każdy niezalogowany gość z ?reset_roles_secret_key na dowolnym URL przywraca domyślne capabilities, w tym to, co celowo ściąłeś z Editor lub Author.

Użyj WP-CLI. wp role reset korzysta z tej samej funkcji core i jest uwierzytelniony dostępem do shella:

wp role reset --all
wp role reset editor

Robi też więcej niż samo populate_roles(), i różnica ma znaczenie przy debugowaniu. populate_roles() woła populate_roles_160() przez populate_roles_300(), a te funkcje tylko add_role() i add_cap(). Nie ma w nich remove_cap(). Wywołane bezpośrednio przywracają usunięte uprawnienia i zostawiają każde dodane przez wtyczkę. WP-CLI robi na tym diff względem czystej instalacji, stąd output w stylu:

Restored 1 capability to and removed 0 capabilities from 'administrator' role.

Własne role żaden z tych ścieżek nie rusza. Jeśli problemem jest popsuta własna rola, reset jej nie naprawi.

Zanim zresetujesz, podejrzyj stan. To jeden wiersz options:

wp option get wp_user_roles --format=json | jq '.editor.capabilities'
wp cap list editor
wp user list --field=user_login --role=administrator

Ostatnie polecenie warto odpalić na każdej stronie, którą dziedziczysz. Liczba administratorów, która Cię zaskakuje, jest już diagnozą.

#5. Jak zabezpieczyć role i uprawnienia WordPress

#Jak sprawdzić konta administratorów w WordPress

Najmniejsze uprawnienie to nie nowa rola, tylko krótsza lista administratorów. Odpal wp user list --role=administrator na stronach, które utrzymujesz. Konta agencji, odejście freelancera i login wsparcia wtyczki sprzed dwóch lat to typowi „lokatorzy”.

#Nazwa użytkownika admin i enumeracja użytkowników przez REST API

Rada „nigdy nie nazywaj użytkownika admin” jest starsza niż instalator pytający o login, a robi to od WordPress 3.0. Zostaje enumeracja: endpoint REST użytkowników zwraca bez uwierzytelnienia id, name, url, description, link, slug i avatar_urls. roles i capabilities należą do kontekstu edit i pozostają ukryte, ale slug to user_nicename, które WordPress wyprowadza z loginu, o ile nikt go nie zmienił. To lista loginów, a nie wyciek, i limit prób na formularzu logowania waży tu więcej.

#Jak wyłączyć edycję plików przez DISALLOW_FILE_EDIT

Usunięcie edit_themes z Administratora to zmiana capability, którą ktoś może cofnąć. Stała w wp-config.php jest sprawdzana w map_meta_cap() i nie da się jej obejść grantem:

define( 'DISALLOW_FILE_EDIT', true );

DISALLOW_FILE_EDIT mapuje edit_files, edit_plugins i edit_themes na do_not_allow. DISALLOW_FILE_MODS idzie dalej: blokuje instalację i aktualizację wtyczek oraz motywów z panelu i wyłącza edytor plików jako efekt uboczny. Na stronie wdrażanej z Gita DISALLOW_FILE_MODS jest uczciwym ustawieniem, bo aktualizacje i tak idą pipeline’em.

DISALLOW_UNFILTERED_HTML działa tak samo i warto ją ustawić na stronie redakcyjnej, gdzie Editorzy nie muszą wklejać skryptów.

#Mapuj meta capabilities na własnych typach treści

register_post_type() domyślnie ustawia map_meta_cap na null, nie false. WP_Post_Type::set_props() potem zamienia null na true, gdy capabilities jest puste i capability_type to post lub page (kompatybilność wsteczna z 3.0, ticket #14122), a w pozostałych przypadkach spada do false. Własny capability_type jak poniżej ląduje więc na false, o ile tego nie powiesz. Ustaw oba argumenty:

register_post_type( 'book', [
    'capability_type' => [ 'book', 'books' ],
    'map_meta_cap'    => true,
] );

Forma tablicowa nie jest ozdobą. Przy zwykłym stringu WordPress dokleja s do liczby mnogiej, stąd storys dla story. Referencja register_post_type() wskazuje tablicę jako sposób podania alternatywnej liczby mnogiej.

capability_type => 'book' generuje meta uprawnienia edit_book, read_book, delete_book oraz prymitywy edit_books, edit_others_books, delete_books, publish_books, read_private_books. Kolejne sześć, read, delete_private_books, delete_published_books, delete_others_books, edit_private_books i edit_published_books, powstaje tylko przy map_meta_cap ustawionym na true, bo konsumuje je wyłącznie map_meta_cap(). To jedyny powód istnienia tej flagi. Bez niej map_meta_cap() zamienia meta uprawnienie edit_book na dosłowny ciąg edit_book, bez sprawdzania autora i statusu publikacji, więc kto ma to uprawnienie, edytuje książki wszystkich.

Jeszcze jedna wartość domyślna: create_posts mapuje się na edit_books, o ile nie ustawisz go jawnie. Rola, która ma edytować istniejące książki, ale nigdy nie tworzyć nowych, wymaga osobnego wpisu w tablicy capabilities.

#Gdzie sprawdzać current_user_can w handlerach i trasach REST

Sprawdzenie należy obok operacji, nie przy menu. add_menu_page() z capability chowa link. Nie chroni handlera. Każdy handler admin-post, callback AJAX i trasa REST potrzebuje własnego current_user_can(), a trasy REST w permission_callback, nie wewnątrz handlera. Od WordPress 5.5 register_rest_route() zgłasza _doing_it_wrong(), gdy permission_callback brakuje, a dla trasy naprawdę publicznej udokumentowaną wartością jest __return_true.

Dla operacji na konkretnym obiekcie przekaż obiekt: current_user_can( 'edit_post', $post_id ) idzie przez map_meta_cap() i rozstrzyga własność. current_user_can( 'edit_posts' ) pyta o typ treści, nie o ten wpis.

#Log audytu dostępu i rozdzielenie środowisk

Log audytu, który śledzi logowania, zmiany ról i wrażliwe akcje, mówi, kto komu co nadał i kiedy. Tę funkcję pokrywają wtyczki takie jak WP Activity Log, a można ją też zbudować na hookach WordPressa.

Role w środowisku deweloperskim, na stagingu i na produkcji przegląda się osobno. Rola rozsądna na dev, z dodatkowymi uprawnieniami do debugowania, może być niebezpieczna na produkcji.

#6. Uprawnienia WordPress w multisite i we wtyczkach

#Uprawnienia sieci w multisite

W WordPress Multisite uprawnienia działają na dwóch poziomach: pojedynczej strony i sieci. Według dokumentacji ról i uprawnień tych dziesięć istnieje tylko dla super admina: create_sites, delete_sites, manage_network, manage_sites, manage_network_users, manage_network_plugins, manage_network_themes, manage_network_options, upgrade_network i setup_network.

Zaskakująca część działa w drugą stronę. Administrator podstrony sieci traci uprawnienia, które ma na single-site. Ta sama dokumentacja wymienia update_core, update_plugins, update_themes, install_plugins, install_themes, delete_themes, delete_plugins, edit_plugins, edit_themes, edit_files, edit_users, add_users, create_users, delete_users i unfiltered_html jako uprawnienia, które w multisite ma tylko super admin. Nie znikają z wiersza roli: map_meta_cap() zamienia je na do_not_allow pod warunkiem is_multisite() && ! is_super_admin( $user_id ), tym samym, który w sekcji 1 widziałeś przy unfiltered_html. Dlatego dodanie install_plugins roli Administrator na podstronie niczego nie zmienia.

WP_User::has_cap() obsługuje super admina, zanim zajrzy do allcaps i zanim zastosuje filtr user_has_cap: jeśli wynik map_meta_cap() nie zawiera do_not_allow, zwraca true. Żeby coś super adminowi odebrać, filtrujesz map_meta_cap i dodajesz do_not_allow, a nie user_has_cap.

Do sprawdzenia uprawnienia na innej stronie sieci WordPress 6.7 wprowadził current_user_can_for_site( $site_id, $capability ), która zastępuje current_user_can_for_blog(), przeniesioną do deprecated.php. Handbook wtyczek wciąż pokazuje starą nazwę.

#Uprawnienia WooCommerce, BuddyPress i bbPress

Wtyczki takie jak WooCommerce, BuddyPress i bbPress dodają do systemu własne uprawnienia. Planując architekturę ról dla strony z tymi wtyczkami, uwzględnij zarówno natywne uprawnienia WordPressa, jak i te dodane przez wtyczki.

#Members i User Role Editor do zarządzania rolami

Wtyczki Members i User Role Editor dają graficzny interfejs do ról i uprawnień. W profesjonalnym developmencie lepiej jednak zarządzać rolami w wersjonowanym kodzie, żeby zmiany uprawnień przechodziły ten sam review co każda inna zmiana.

#Podsumowanie

Role to magazyn. Capabilities to decyzja. Cały przewodnik wynika z tego podziału:

  • Sprawdzaj capabilities, nigdy nazw ról, bo current_user_can('administrator') przechodzi przez merge kluczy meta użytkownika i zwraca false dla każdej własnej roli, którą zbudujesz.
  • Traktuj add_role() i add_cap() jak migracje wiersza w bazie, z bramką wersji, a nie jak konfigurację, którą edytujesz i wdrażasz.
  • Czytaj realny zakres capability przed grantem. edit_theme_options przy motywie blokowym to Site Editor, nie tylko ekran menu.
  • Odzyskuj przez wp role reset --all, nigdy przez nieuwierzytelniony parametr w URL, i pamiętaj, że własne role zostawia w spokoju.
  • Ustaw map_meta_cap => true na każdym własnym typie treści z więcej niż jednym autorem.

Audyt listy administratorów i mapy uprawnień: audyt bezpieczeństwa WordPress albo kontakt.

Następny krok

Przekuj artykuł w realne wdrożenie

Pod tym wpisem dokładam linki, które domykają intencję użytkownika i prowadzą dalej w strukturze serwisu.

Powiązany klaster

Sprawdź inne usługi WordPress i bazę wiedzy

Wzmocnij swój biznes dzięki profesjonalnemu wsparciu technicznemu w kluczowych obszarach ekosystemu WordPress.

FAQ do artykułu

Często zadawane pytania

Najważniejsze odpowiedzi, które pomagają wdrożyć temat w praktyce.

SEO-readyGEO-readyAEO-ready5 Q&A
Jaka jest różnica między rolą a capability w WordPressie?#
Capability to pojedynczy ciąg uprawnienia, na przykład edit_posts albo manage_options. Rola to nazwany zestaw takich ciągów zapisany w options. WordPress sprawdza capability w momencie decyzji, więc rola ma znaczenie tylko jako kontener, który to uprawnienie dostarcza.
Czy w kodzie lepiej sprawdzać rolę czy capability?#
Capability. current_user_can('administrator') działa przypadkiem, bo WP_User::get_role_caps() scala meta użytkownika, gdzie nazwy ról są kluczami, do allcaps. Dla własnej roli z manage_options zwraca false i blokuje użytkownika, dla którego tę rolę zbudowałeś.
Jak zresetować popsute role w WordPressie?#
Uruchom wp role reset --all przez WP-CLI. Wywołuje populate_roles() i robi diff, więc przywraca usunięte domyślne uprawnienia i usuwa dodane. Samo populate_roles() tylko dokłada brakujące, bo funkcje populate_roles_* nigdy nie wołają remove_cap().
Dlaczego add_role() ignoruje nowe uprawnienie?#
add_role() zapisuje do bazy raz. Handbook wtyczek mówi wprost, że kolejne wywołania nic nie robią, także przy zmianie listy capabilities. Trzymaj numer wersji w opcji, porównuj przy aktywacji i przy zmianie wywołaj remove_role(), a potem add_role().
Które uprawnienie steruje Site Editorem w motywie blokowym?#
Głównie edit_theme_options. WordPress sprawdza je na endpointach REST szablonów i części szablonów. Pełne użycie Site Editora zwykle wymaga też edit_posts, edit_pages, edit_others_posts, read i upload_files.

Potrzebujesz FAQ dopasowanego do branży i rynku? Przygotujemy wersję pod Twoje cele biznesowe.

Porozmawiajmy

Polecane artykuły