Skip to content

Instantly share code, notes, and snippets.

@rich97
Created October 24, 2011 11:43
Show Gist options
  • Save rich97/1308837 to your computer and use it in GitHub Desktop.
Save rich97/1308837 to your computer and use it in GitHub Desktop.
CMS concept.

Introduction

Today’s CMS systems work by providing an environment for a developer to work in. You modify the data in the admin panel and them CMS provides a method of inserting the HTML it generates into your templates.

However, therein lies the problem -- the output is generated by the CMS. The CMS should exist to provide a user friendly abstraction to the websites dynamic content. It should not tell the frontend how to represent that content.

To anyone reading this, please be aware that any examples I give will be framed within the context of the MVC pattern and more specifically the Lithium PHP framework. Why? Because these are the tools I love to use at the time of writing this document, although there is no reason that this couldn’t be adapted.

Proposed solution

My initial thought was to provide a REST API to the backend. If you wanted to extend the base CMS system you would fist create a GUI interface in the admin panel to manipulate the content and then create an API interface to that data so that the frontend can access it.

As I see it, there are a few benefits and drawbacks to this approach.

Benefits

  • The admin panel could be hosted on a different server making a centralized CMS possible.
  • The CMS that was created would be language and framework independent of the frontend.
  • Would be easy to adapt to provide services to third-parties.
  • DRY and portable code. The admin interface is a centralized location to modify the sites dynamic data, the frontend only exists to display it. Meaning that any changes made to how the backend works will affect the frontend less often than it would using the traditional model.
  • Easy to use with AJAX.

Drawbacks

  • Security. Obviously providing a service without severe consideration to security means that anyone can easily steal your content. That’s not good.
  • Generates more HTTP requests.
  • Not a good model for anyone but professional developers.

I haven’t given much thought as to what would be an appropriate security model as of yet. It’s complicated because you may want to make some services public, but not others.

However, there is a way to combat the first two drawbacks easily; allow the models to define the API provided and create a “request broker” to access those models via any number of adapters.

I’m probably not explaining this very well so let me give an example. In this example we have a model “Users” with the methods “login” and “logout”.

namespace admin\models\Users;

class Users extends \lithium\data\Model {

    public function login($username, $password) {
        /**
         * returns a login token for the user
         * to authenticate with certain API methdos
         **/
    }

    public function logout() {
        // makes the login token no longer work
    }

}

RequestBroker has two adapters; “simple” and “http”. Here are two example configurations:

RequestBroker::config(
    'simple' => array(
        'driver' => 'simple',
        'type'   => 'json'
    ),
    'http'   => array(
        'driver' => 'http',
        'token'  => 'sUp4s3cr3t', // this would need to be generated in the admin panel
        'url'    => ‘www.example.com’
        'type'   => 'json',
        'ssl'    => true
    )
));

RequestBroker provides four static methods for all of the basic CRUD operations. So by calling:

RequestBroker::post('simple', '/users/login', array(
    'username' => 'rich97',
    'password' => 'password'
));

Request broker would directly try to call \admin\models\Users::login($username, $password); if the method was not found it would return some JSON or XML to inform the developer something went wrong, or maybe it would throw an exception in this case.

However if we did:

RequestBroker::post('http', '/users/login', array(
   'username' => 'rich97',
   'password' => 'password'
));

It would create a new HTTP request to https://www.example.com/users/login and attempt to authenticate with the service provider and the service.

This way, if you didn’t need to use the remote request, you don’t have to. Your application stays secure and doesn’t generate any extra HTTP requests.

Let me know what you think, this is just a quick and dirty write up. I’ll develop the idea further or ditch it completely based on the feedback I receive.

@rmarscher
Copy link

I've been working on similar issues -- basically SaaS applications (your centralized CMS is like a Saas) where the front-end is hosted and developed elsewhere and uses an api to communicate with the core application that does the business logic. For security, I'm thinking oauth 2.0 is the way to go. Obviously a javascript sdk wouldn't have the api secret - it would have an api key and the core app could verify the api key against a list of domains that are allowed to use it.

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