Blueprint by Tiny
Return to Tiny.cloud
Return to Tiny.cloudTry TinyMCE for Free
Search by
Tiny Drive UI

Tiny Drive Developer Guide

Robert Collings

November 14th, 2018

Written by

Robert Collings
Robert Collings

Category

Tips & How-Tos

The "rich" in rich text editing generally means adding images, videos, and other files that are embedded in your content. This involves file management, and until now, developers have had to undertake the difficult and time-consuming task of wiring up file upload and management themselves.

To solve this issue, we created Tiny Drive, a new cloud-based asset management and storage service. If you've ever marveled at Dropbox's ease of use, or considered MoxieManager for self-hosted asset management but were discouraged by the server requirements, then Drive will be an excellent solution for your team.

Drive automatically uploads and stores images, videos, and files when they are added to TinyMCE while editing content. It also provides the ability to manage files using a very familiar user interface. Drive is automatically provisioned for all Tiny Cloud accounts, and there is even a free tier that includes 100MB of storage and 1GB bandwidth.

Let's get to it.

Part 1. Configure TinyMCE

If TinyMCE is already set up, you will have a config that looks something like the one below. It's likely that you have a more complex init, possibly used a different HTML element for the selector, or you might even call an advanced config from an external JS file. Whatever your config looks like, in this section our focus is TinyMCE's init.

<!DOCTYPE html>
  <html>
    <head>
      <script src="https://cloud.tinymce.com/stable/tinymce.min.js"></script>
      <script>tinymce.init ({ selector:'textarea' });</script>
    </head>
    <body>
      <textarea>Next, let's add Tiny Drive</textarea>
    </body>
  </html>

The next steps update tinymce.init with the options required to connect to the Drive service.

If you are not familiar with configuring TinyMCE, you might like to take a quick look at our Quick Start or General Configuration guide.

1. Add the "tinydrive" plugin

First, add tinydrive to the plugins key:

tinymce.init({
  selector: 'textarea',
  plugins: 'tinydrive'
});

2. Declare JWT token provision

Next, declare how the JWT token will be provisioned. First, add the tinydrive_token_provider key with either a Provider URL or a Provider Callback as the key pair.

Example using a JWT Provider URL

In this option, use a URL to a page that takes an HTTP JSON POST request and produces a JSON structure with a valid JWT. It uses a POST request to avoid caching by browsers and proxies.

tinymce.init({
  selector: 'textarea',
  plugins: 'tinydrive',
  tinydrive_token_provider: '/jwt'
});

Example using a JWT Provider Callback

The other option is to use a function that provides the same token through a callback. This allows you to make your own HTTP request in any format you like. The provider function is a function that has a success and failure callback where success takes an object with a token property containing the JWT, and the failure callback takes a string to present as an error message if the token could not be produced.

tinymce.init({
  selector: 'textarea',
  plugins: 'tinydrive',
  tinydrive_token_provider: function (success, failure) {
     success({ token: 'jwt-token' });
     // failure('Could not create a jwt token')
  }
});

How to create a token will be explained later in this guide.

3. File upload path

By default, all objects will be uploaded to the path /uploads. Using the tinydrive_upload_path config option you can change the default path for files that get uploaded when pasted into the editor, uploaded directly through the Image dialog, or when you drag-and-drop images into the editor. It will produce a date-based structure within this path like this /uploads/{year}{month}{day}. We do this to avoid placing thousands of files in the same directory.

tinymce.init({
  selector: 'textarea',
  plugins: 'tinydrive',
  tinydrive_upload_path: '/some/other/path'
});

4. Add an Insert File toolbar button

Drive will automatically integrate into the ImageLink, and Media dialogs as a file picker. You can also configure it to insert files directly into your content using the insertfile button. To enable this button, add it to your toolbar editor setting.

tinymce.init({
  selector: 'textarea',
  plugins: 'tinydrive',
  toolbar: 'insertfile'
});

The Insert File toolbar button will insert images as img elements and other files as links to that file.

Note that the process of declaring a toolbar value specifically overrides the default toolbar config. It will need to be rebuilt manually. An advantage is that you will end up with the exact toolbar config you want, rather than what we deliver out of the box.

5. Add an Insert File menu item

Now that you have a toolbar button set up, you should consider adding a menu item also. To do this add it to the menu editor setting or the insert_button_items setting. As with the toolbar mentioned above, declaring a menu value overrides the default config.

tinymce.init({
  selector: 'textarea',
  plugins: 'tinydrive',
  toolbar: 'insertfile',
  menu: {
    insert: { title: 'Insert', items: 'insertfile' }
  },
  insert_button_items: 'insertfile'
});

Full example config using JWT Token Callback

tinymce.init({
  selector: 'textarea',
  plugins: 'tinydrive',
  tinydrive_upload_path: '/some/other/path',
  tinydrive_token_provider: function (success, failure) {
     success({ token: 'jwt-token' });
     // failure('Could not create a jwt token')
  },
  toolbar: 'insertfile',
  menu: {
    insert: { title: 'Insert', items: 'insertfile' }
  },
  insert_button_items: 'insertfile'
});

In Part 2 we'll show you how to set up JWT authentication for Drive.

Part 2. JWT Authentication

Some TinyMCE cloud-based services require JWT authentication. This allows us to verify that you and your end user are allowed to access a particular feature. JWT is a common authorization solution for web services and is documented in more detail at the https://jwt.io/ website. This section of the guide aims to show how to setup JWT authentication for TinyMCE's cloud services.

Before starting, this section assumes prior knowledge of JSON Web Token (or JWT), including how they can be used for user authentication and session management in a web application. Some coding on both the client-side and the server-side is required to configure JWT as per the instructions in this section.

Private/Public Key Pair

Tokens used by the TinyMCE cloud services make use of a public/private RSA key-pair. This allows you as an integrator to have full control over the authentication as we don't store the private key.

Only you have access to the private key, and only you can produce valid tokens. We can only verify that the tokens are valid and extract user information from that token.

Public key creation

The private/public key pair is created using the Tiny account JWT key manager page. Detailed instructions are provided on the keygen page itself, and (again) be assured we only store the public key on our side. The private key is for you to store in your backend.

JWT Provider URL

The easiest way to setup JWT authentication against TinyMCE cloud services is to create a JWT provider endpoint. This endpoint takes a JSON HTTP POST request and produces a JSON result with the token that the service will then use for all the HTTP requests.

The following diagram explains the JWT call flow:

Tiny Drive JWT call flow

JWT requirements

1. Algorithm

The following algorithms are supported for the JWT header/signature:

  • RS256
  • RS384
  • RS512
  • PS256
  • PS384
  • PS512

All of these algorithms use the private RSA key to sign the JWT, but vary in how they execute. RS256, the most widely supported algorithm, features in the code examples below.

2. Drive specific JWT Claims

  • sub - (required) Unique string to identify the user. This can be a database ID, hashed email address, or similar identifier.
  • name - (required) Full name of the user that will be used for presentation inside Drive. When the user uploads a file, this name is presented as the creator of that file.

Node Token Provider example

This example shows how to set up a Node.js express handler that produces the tokens. It requires the Express web framework and the jsonwebtoken Node modules to be installed. Each service requires different claims to be provided. The following example shows the sub and name claims needed for Drive.

const express = require('express');
const jwt = require('jsonwebtoken');
const cors = require('cors');

const app = express();
app.use(cors());


const privateKey = 
-----BEGIN PRIVATE KEY----- .... -----END PRIVATE KEY-----
;


app.post('/jwt', function (req, res) {
  const payload = {
    sub: '123',         // Unique user id string
    name: 'John Doe',   // Full name of user
    exp: Math.floor(Date.now() / 1000) + (60 * 10) // 10 minutes expiration
  };
  try {
    const token = jwt.sign(payload, privateKey, { algorithm: 'RS256'});
    res.set('content-type', 'application/json');
    res.status(200);
    res.send(JSON.stringify({
      token: token
    }));
  } catch (e) {
    res.status(500);
    res.send(e.message);
  }
});
app.listen(3000);

PHP Token Provider example

This example uses the Firebase JWT library provided through the Composer dependency manager. The private key should be the private key that was generated through your Tiny Account. Each service requires different claims to be provided. The following example shows the sub and name claims needed for Drive.

<?php
require 'vendor/autoload.php';
use \Firebase\JWT\JWT;

header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");


$privateKey = <<<EOD
-----BEGIN PRIVATE KEY-----
....
-----END PRIVATE KEY-----
EOD;


$payload = array(
  "sub" => "123",           // Unique user id string
  "name" => "John Doe",     // Full name of user
  "exp" => time() + 60 * 10 // 10 minutes expiration
);


try {
  $token = JWT::encode($payload, $privateKey, 'RS256');
  http_response_code(200);
  header('Content-Type: application/json');
  echo json_encode(array("token" => $token));
} catch (Exception $e) {
  http_response_code(500);
  header('Content-Type: application/json');
  echo $e->getMessage();
}
?>

Drive restrictions and quotas

An important note about some restrictions Drive has on the types of files that can be uploaded and the size of these files:

  • The maximum file size is 100MB
  • Allowed image extensions: gif, jpeg, jpg, png, tif, tiff, bmp
  • Allowed document extensions: doc, xls, ppt, pps, docx, xlsx, pptx, pdf, rtf, txt, keynote, pages, numbers
  • Allowed audio extensions: wav, wave, mp3, ogg, ogv, oga, ogx, ogm, spx, opus
  • Allowed video extensions: mp4, m4v, ogv, webm, mov
  • Allowed archive extensions: zip
  • The Copy operation is limited to single files due to technical reasons

Storage and bandwidth quota vary based upon your subscription. All Tiny Cloud accounts start with 100MB storage and 1GB bandwidth included free. Sign up to get started.

Upload URLs

All files are uploaded to a central storage with a CDN endpoint, which means that we host your files and that they are publicly available in read-only mode for anyone that has access to the URL of that file. The URL format for each file is https://drive.tiny.cloud/1/{your-api-key}/{uuid}, which gets generated when a file is uploaded. If a file is moved or renamed, it will still have the same unique URL, so the restructuring of files using Drive will not affect where they are used. However, deleting a file will mark the URL as unused, and the URL will not continue to work.

Next steps

You are only a few steps away from attaching free, cloud file management to TinyMCE. Here's a quick review:

  1. Create a Tiny Cloud account (if you haven't already)
  2. Configure the editor
  3. Create JWT Authentication and a Provider using our Node or PHP examples

If you have any questions about setting up Tiny Drive, the TinyMCE Community is a great place to get help.

Tiny Drive
Robert Collings
byRobert Collings

Robert Collings is a Marketing Director at Tiny, responsible for our global event, field, channel and partner marketing programs. With a background in the music and publishing industries, in his spare time you'll find him listening to tunes, practicing Brazilian Jiu-Jitsu, and "doing dad stuff". Hit him up on LinkedIn if you'd like to chat marketing.

Related Articles

  • Neon sign of speech ballon with text: 'hello'.
    Tips & How-Tos

    Neon fonts and glowing text: get started in two steps

    by Ben Long in Tips & How-Tos

Build beautiful content for the web with Tiny.

The rich text editing platform that helped launch Atlassian, Medium, Evernote and more.

Begin my FREE 30 day trial
Tiny Editor