├── README.md
├── assets
├── banner-1544x500.png
├── banner-772x250.png
├── icon-128x128.png
├── icon-256x256.png
└── screenshot-1.png
├── composer.json
├── frontity-embedded.php
├── includes
├── admin-page.php
├── capability-tokens.php
├── error.php
├── php-jwt
│ ├── BeforeValidException.php
│ ├── ExpiredException.php
│ ├── JWK.php
│ ├── JWT.php
│ └── SignatureInvalidException.php
└── template.php
├── package.json
└── readme.txt
/README.md:
--------------------------------------------------------------------------------
1 | # Frontity - Embedded Mode
2 |
3 | For a full explanation please refer to the [Embedded mode documentation](https://api.frontity.org/frontity-plugins/embedded-mode). If you have any questions related to the plugin feel free to share them in [Frontity community forum](https://community.frontity.org/).
4 |
5 | ## Install
6 |
7 | 1. First of all you have to install the plugin. [Download the plugin from GitHub](https://github.com/frontity/frontity-embedded/archive/refs/heads/master.zip) and upload it to your web server. For a more detailed explanation, WordPress explains how to do this [on this guide](https://wordpress.org/support/article/managing-plugins/#manual-plugin-installation).
8 | 2. Once installed, you have to activate it, go to Settings -> Frontity Embedded Mode, and define the proper Frontity Server Url. and it will be running!
9 |
10 | > Revisions are necessary to do post previews, so make sure those are activated for both your posts, pages and any custom post types.
11 |
12 | ## Environment Variables
13 |
14 | You can also use an environment variable instead of changing the URL in the plugin interface.
15 |
16 | ```php
17 | > FRONTITY_SERVER=https://myfrontityserver.com
18 | ```
19 |
20 | ## WordPress Constant
21 |
22 | Lastly a PHP constant can be defined. This would usually be done in the wp-config.php file.
23 |
24 | ```
25 | define( 'FRONTITY_SERVER', 'https://myfrontityserver.com' );
26 | ```
27 |
28 | Note that if the PHP constant exists, it takes precedence over both the environment variable and the settings page setting.
29 |
30 | ## Static Assets
31 |
32 | If you need, you can change the folder or URL where your static assets are stored using the `--public-path` option of the `npx frontity build` command.
33 |
34 | ### Example: Frontity in the same WordPress server
35 |
36 | If you are using the same server for both WordPress and Frontity, and your Frontity project is at `/wp-content/frontity`, your static folder will be at `https://yourdomain.com/wp-content/frontity/build/static`.
37 |
38 | You can change the folder when you run `npx frontity build` like this:
39 |
40 | ```bash
41 | > npx frontity build --public-path /wp-content/frontity/build/static
42 | ```
43 |
44 | ### Example: Frontity in an external server
45 |
46 | If you deployed Frontity in an external hosting service, like for example Vercel, you can use the `--public-path` option to point directly to the Vercel URL:
47 |
48 | ```bash
49 | > npx frontity build --public-path https://myfrontityapp.now.sh/static
50 | ```
51 |
52 | ## Local Development
53 |
54 | If you want to use the Embedded mode while you are developing in your local environment, you can do so by using the `--public-path` parameter in the `npx frontity dev` command as well:
55 |
56 | ```bash
57 | > npx frontity dev --public-path http://localhost:3000/static
58 | ```
59 |
60 | ---
61 |
62 | ## Frontity Channels 🌎
63 |
64 | [](https://community.frontity.org/) [](https://twitter.com/frontity) 
65 |
66 | We have different channels at your disposal where you can find information about the Frontity project, discuss it and get involved:
67 |
68 | - 📖 **[Docs](https://docs.frontity.org)**: this is the place to learn how to build amazing sites with Frontity.
69 | - 👨👩👧👦 **[Community](https://community.frontity.org/)**: use our forum to [ask any questions](https://community.frontity.org/c/dev-talk-questions), feedback and meet great people. This is your place too to share [what are you building with Frontity](https://community.frontity.org/c/community/showcases/19)!
70 | - 🐞 **[GitHub](https://github.com/frontity)**: we use GitHub for bugs and pull requests. Questions are answered in the [community forum](https://community.frontity.org/)!
71 | - 🗣 **Social media**: a more informal place to interact with Frontity users, reach out to us on [Twitter](https://twitter.com/frontity).
72 | - 💌 **Newsletter**: do you want to receive the latest framework updates and news? Subscribe [here](https://frontity.org/)
73 |
74 | ### » Get involved 🤗
75 |
76 | Got questions or feedback about Frontity? We'd love to hear from you. Use our [community forum](https://community.frontity.org) yo ! ❤️
77 |
78 | Frontity also welcomes contributions. There are many ways to support the project! If you don't know where to start, this guide might help: [How to contribute?](https://docs.frontity.org/contributing/how-to-contribute)
79 |
--------------------------------------------------------------------------------
/assets/banner-1544x500.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frontity/frontity-embedded/6941adef1f3c45095ba39b359379e0c8a395ab9f/assets/banner-1544x500.png
--------------------------------------------------------------------------------
/assets/banner-772x250.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frontity/frontity-embedded/6941adef1f3c45095ba39b359379e0c8a395ab9f/assets/banner-772x250.png
--------------------------------------------------------------------------------
/assets/icon-128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frontity/frontity-embedded/6941adef1f3c45095ba39b359379e0c8a395ab9f/assets/icon-128x128.png
--------------------------------------------------------------------------------
/assets/icon-256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frontity/frontity-embedded/6941adef1f3c45095ba39b359379e0c8a395ab9f/assets/icon-256x256.png
--------------------------------------------------------------------------------
/assets/screenshot-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/frontity/frontity-embedded/6941adef1f3c45095ba39b359379e0c8a395ab9f/assets/screenshot-1.png
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "frontity/frontity-embedded",
3 | "description": "Embedded Mode plugin for Frontity sites",
4 | "type": "wordpress-plugin",
5 | "license": "GPLv2",
6 | "authors": [
7 | {
8 | "name": "Frontity",
9 | "homepage": "https://frontity.org"
10 | }
11 | ],
12 | "require": {}
13 | }
14 |
--------------------------------------------------------------------------------
/frontity-embedded.php:
--------------------------------------------------------------------------------
1 | ''
64 | ) );
65 | }
66 | register_activation_hook( __FILE__, 'frontity_embedded_activate' );
67 |
68 | /**
69 | * Delete settings on uninstall.
70 | */
71 | function frontity_embedded_uninstall() {
72 | delete_option( 'frontity_embedded_plugin_settings' );
73 | }
74 | register_uninstall_hook( __FILE__, 'frontity_embedded_uninstall' );
75 |
--------------------------------------------------------------------------------
/includes/admin-page.php:
--------------------------------------------------------------------------------
1 |
16 |
17 |
Frontity Embedded Mode
18 |
For detailed information and usage instructions please refer to the documentation page.
19 |
26 |
27 | 'frontity_embedded_validate_settings'
36 | )
37 | );
38 |
39 | add_settings_section(
40 | 'frontity_embedded_plugin_section',
41 | '',
42 | '__return_empty_string',
43 | 'frontity_embedded_plugin_page'
44 | );
45 |
46 | add_settings_field(
47 | 'frontity_server',
48 | 'Frontity Server URL',
49 | 'frontity_embedded_frontity_server_input',
50 | 'frontity_embedded_plugin_page',
51 | 'frontity_embedded_plugin_section'
52 | );
53 | }
54 | add_action( 'admin_init', 'frontity_embedded_register_settings' );
55 |
56 | function frontity_embedded_validate_settings( $input ) {
57 | $output['frontity_server'] = esc_url( sanitize_text_field( $input['frontity_server'] ) );
58 | return $output;
59 | }
60 |
61 | function frontity_embedded_frontity_server_input() {
62 | $options = get_option( 'frontity_embedded_plugin_settings' );
63 | printf(
64 | '',
65 | esc_attr( 'frontity_embedded_plugin_settings[frontity_server]' ),
66 | esc_attr( $options['frontity_server'] )
67 | );
68 | }
69 |
--------------------------------------------------------------------------------
/includes/capability-tokens.php:
--------------------------------------------------------------------------------
1 | $issued_at,
35 | // Expire the token in 60 seconds.
36 | "exp" => $issued_at + MINUTE_IN_SECONDS,
37 | 'type' => $payload['type'],
38 | 'post_type' => $payload['post_type'],
39 | 'post_id' => $payload['post_id'],
40 | 'generator' => 'frontity'
41 | );
42 |
43 | return JWT::encode($payload, Frontity_Embedded_Capability_Tokens::get_private_key());
44 | }
45 |
46 | /**
47 | * Validate a token using args.
48 | */
49 | public static function check_capability( $args ) {
50 | $payload = (array) Frontity_Embedded_Capability_Tokens::$payload;
51 |
52 | // Do not authenticate if the token was not generated by Frontity.
53 | if ( $payload['generator'] !== 'frontity' ) return false;
54 | // Do not authenticate if the token is not for the preview.
55 | if ( $payload['type'] !== 'preview' ) return false;
56 | // Prevent using the token for requests that are not GET.
57 | if ( isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] !== "GET" ) return false;
58 | // Prevent using the token for requests that are GET, but use the
59 | // `_method` query to override the method.
60 | if ( isset( $_GET['_method'] ) && $_GET[ '_method' ] !== "GET" ) return false;
61 | // Prevent using the token for requests that are GET, but use the
62 | // `X-HTTP-Method-Override` header to override the method.
63 | if ( isset( $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] ) && $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] !== "GET" ) return false;
64 |
65 | $post_id = $payload['post_id'];
66 | $post_type = $payload['post_type'];
67 |
68 | // Allowed capabilites when the token is type 'preview'. You also need to
69 | // have permission to 'edit_post' or 'delete_post' for preview posts.
70 | $capabilities = array(
71 | 'read_post' => $post_id,
72 | 'edit_post' => $post_id,
73 | 'delete_post' => $post_id,
74 | );
75 |
76 | // Prior to WordPress 5.5.1, capabilities should be specified with `page`
77 | // for pages, so we are adding them as well to support older versions of
78 | // WordPress.
79 | if ( $post_type === 'page' ) {
80 | $capabilities = array_merge( $capabilities, array(
81 | "read_page" => $id,
82 | "edit_page" => $id,
83 | "delete_page" => $id,
84 | ) );
85 | }
86 |
87 | // Use key-value to check capabilities with an associated ID.
88 | if ( count( $args ) === 3 ) {
89 | // Get capability and ID.
90 | list( $cap, $_, $id ) = $args;
91 | // Find that capability in the capabilities array.
92 | return isset( $capabilities[ $cap ] ) && $capabilities[ $cap ] === $id;
93 | }
94 |
95 | // If it is a global capability, check if it is included as value.
96 | list( $cap ) = $args;
97 | return in_array( $cap, $capabilities );
98 | }
99 |
100 | /**
101 | * Modify user capabilities on run time.
102 | */
103 | public static function user_has_cap( $allcaps, $caps, $args, $user ) {
104 | // Add capability if it is allowed in the token.
105 | if ( Frontity_Embedded_Capability_Tokens::check_capability( $args )) {
106 | foreach ( $caps as $cap ) {
107 | $allcaps[ $cap ] = true;
108 | }
109 | }
110 |
111 | // Return capabilities.
112 | return $allcaps;
113 | }
114 |
115 | /**
116 | * Return the private key used to encode and decode tokens.
117 | */
118 | private static function get_private_key() {
119 | if ( defined( 'FRONTITY_JWT_AUTH_KEY' ) )
120 | return FRONTITY_JWT_AUTH_KEY;
121 |
122 | if ( defined( 'SECURE_AUTH_KEY' ) )
123 | return SECURE_AUTH_KEY;
124 |
125 | // No secure auth key found. Throw an error.
126 | $error = new WP_Error(
127 | 'no-secure-auth-key',
128 | 'Please define either SECURE_AUTH_KEY or FRONTITY_JWT_AUTH_KEY in your wp-config.php file.'
129 | );
130 | throw new Exception( $error->get_error_message() );
131 | }
132 |
133 | /**
134 | * Decode capability tokens if present.
135 | */
136 | private static function get_payload_from_token() {
137 | // Get HTTP Authorization Header.
138 | $header = isset( $_SERVER['HTTP_AUTHORIZATION'] )
139 | ? sanitize_text_field( $_SERVER['HTTP_AUTHORIZATION'] )
140 | : false;
141 |
142 | // Check for alternative header.
143 | if ( ! $header && isset( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ) ) {
144 | $header = sanitize_text_field( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] );
145 | }
146 |
147 | // No Authorization Header is present.
148 | if ( ! $header ) return null;
149 |
150 | // Get and parse the token.
151 | try {
152 | list( $token ) = sscanf( $header, 'Bearer %s' );
153 | $payload = JWT::decode(
154 | $token,
155 | Frontity_Embedded_Capability_Tokens::get_private_key(),
156 | array('HS256')
157 | );
158 | } catch (Exception $e) {
159 | // Token is not valid.
160 | return null;
161 | }
162 |
163 | // Return the parsed token.
164 | return $payload;
165 | }
166 | }
--------------------------------------------------------------------------------
/includes/error.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - Server Error
5 | ";
9 | }
10 | ?>
11 |
49 |
50 |
51 |
52 | " . get_bloginfo( 'name' ) . "";
58 | }
59 | ?>
60 | There was a problem loading this page. Try again or come back later.