Improvement for OAuth2 Server. Implicit, Resource Owner Password and Client Credentials were added, and refactoring of oauth2 endpoints
This commit is contained in:
@@ -18,6 +18,8 @@ class Restler extends \Luracast\Restler\Restler
|
|||||||
public $responseMultipart = array();
|
public $responseMultipart = array();
|
||||||
public $inputExecute = '';
|
public $inputExecute = '';
|
||||||
|
|
||||||
|
protected $workspace;
|
||||||
|
|
||||||
public function __construct($productionMode = false, $refreshCache = false)
|
public function __construct($productionMode = false, $refreshCache = false)
|
||||||
{
|
{
|
||||||
parent::__construct($productionMode, $refreshCache);
|
parent::__construct($productionMode, $refreshCache);
|
||||||
@@ -127,4 +129,14 @@ class Restler extends \Luracast\Restler\Restler
|
|||||||
{
|
{
|
||||||
$this->message($e);
|
$this->message($e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setWorkspace($workspace)
|
||||||
|
{
|
||||||
|
$this->workspace = $workspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getWorkspace()
|
||||||
|
{
|
||||||
|
return $this->workspace;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
29
framework/src/Maveriks/Pattern/Mvc/SmartyView.php
Normal file
29
framework/src/Maveriks/Pattern/Mvc/SmartyView.php
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
namespace Maveriks\Pattern\Mvc;
|
||||||
|
|
||||||
|
class SmartyView extends View
|
||||||
|
{
|
||||||
|
protected $smarty;
|
||||||
|
|
||||||
|
public function __construct($tpl = '')
|
||||||
|
{
|
||||||
|
parent::__construct($tpl);
|
||||||
|
require_once PATH_THIRDPARTY . 'smarty/libs/Smarty.class.php'; //
|
||||||
|
|
||||||
|
$this->smarty = new \Smarty();
|
||||||
|
$this->smarty->compile_dir = defined('PATH_SMARTY_C')? PATH_SMARTY_C : sys_get_temp_dir();
|
||||||
|
$this->smarty->cache_dir = defined('PATH_SMARTY_CACHE')? PATH_SMARTY_CACHE : sys_get_temp_dir();
|
||||||
|
//$this->smarty->config_dir = PATH_THIRDPARTY . 'smarty/configs';
|
||||||
|
//$this->smarty->register_function('translate', 'translate');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function assign($name, $value)
|
||||||
|
{
|
||||||
|
$this->smarty->assign($name, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
$this->smarty->display($this->getTpl());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -96,6 +96,8 @@ class WebApplication
|
|||||||
*/
|
*/
|
||||||
public function route()
|
public function route()
|
||||||
{
|
{
|
||||||
|
$this->requestUri = strlen($this->requestUri) > 1? rtrim($this->requestUri, '/'): $this->requestUri;
|
||||||
|
|
||||||
if ($this->requestUri === "/") {
|
if ($this->requestUri === "/") {
|
||||||
if (file_exists("index.html")) {
|
if (file_exists("index.html")) {
|
||||||
return self::RUNNING_INDEX;
|
return self::RUNNING_INDEX;
|
||||||
@@ -107,7 +109,47 @@ class WebApplication
|
|||||||
) {
|
) {
|
||||||
return self::RUNNING_API;
|
return self::RUNNING_API;
|
||||||
} else {
|
} else {
|
||||||
return self::RUNNING_WORKFLOW;
|
list($this->requestUri,) = explode('?', $this->requestUri);
|
||||||
|
$uriParts = explode('/', $this->requestUri);
|
||||||
|
|
||||||
|
if ($uriParts[2] == 'oauth2') {
|
||||||
|
|
||||||
|
if (! isset($uriParts[2])) {
|
||||||
|
return self::RUNNING_WORKFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*$workspace = $uriParts[1];
|
||||||
|
$class = 'oauth2';
|
||||||
|
$action = isset($uriParts[3])? $uriParts[3]: 'index';*/
|
||||||
|
|
||||||
|
$uriTemp = explode('/', $_SERVER['REQUEST_URI']);
|
||||||
|
array_shift($uriTemp);
|
||||||
|
$workspace = array_shift($uriTemp);
|
||||||
|
$_SERVER['REQUEST_URI'] = '/' . implode('/', $uriTemp);
|
||||||
|
|
||||||
|
$this->loadEnvironment($workspace);
|
||||||
|
$this->configureRest($workspace, '1.0');
|
||||||
|
//var_dump(class_exists('ProcessMaker\\Services\\OAuth2\\Server'));
|
||||||
|
$this->rest->addAPIClass('\ProcessMaker\\Services\\OAuth2\\Server', 'oauth2');
|
||||||
|
$this->rest->handle();
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
$this->loadEnvironment($workspace);
|
||||||
|
|
||||||
|
require_once PATH_CONTROLLERS . $class . '.php';
|
||||||
|
|
||||||
|
if (is_callable(array($class, $action))) {
|
||||||
|
$controller = new $class();
|
||||||
|
$controller->setHttpRequestData($_REQUEST);
|
||||||
|
$controller->call($action);
|
||||||
|
} else {
|
||||||
|
header('location: /errors/error404?url=' . urlencode($this->requestUri));
|
||||||
|
}*/
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return self::RUNNING_WORKFLOW;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,8 +269,6 @@ class WebApplication
|
|||||||
$apiIniFile = $servicesDir . DS . 'api.ini';
|
$apiIniFile = $servicesDir . DS . 'api.ini';
|
||||||
// $authenticationClass - contains the class name that validate the authentication for Restler
|
// $authenticationClass - contains the class name that validate the authentication for Restler
|
||||||
$authenticationClass = 'ProcessMaker\\Services\\OAuth2\\Server';
|
$authenticationClass = 'ProcessMaker\\Services\\OAuth2\\Server';
|
||||||
// $pmOauthClientId - contains PM Local OAuth Id (Web Designer)
|
|
||||||
$pmOauthClientId = 'x-pm-local-client';
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Load Api ini file for Rest Service
|
* Load Api ini file for Rest Service
|
||||||
@@ -252,37 +292,9 @@ class WebApplication
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setting current workspace to Api class
|
$this->configureRest(SYS_SYS, $version, $multipart);
|
||||||
Services\Api::setWorkspace(SYS_SYS);
|
|
||||||
$cacheDir = defined("PATH_C")? PATH_C: sys_get_temp_dir();
|
|
||||||
|
|
||||||
$sysConfig = \System::getSystemConfiguration();
|
|
||||||
|
|
||||||
\Luracast\Restler\Defaults::$cacheDirectory = $cacheDir;
|
|
||||||
$productionMode = (bool) !(isset($sysConfig["service_api_debug"]) && $sysConfig["service_api_debug"]);
|
|
||||||
|
|
||||||
Util\Logger::log("Serving API mode: " . ($productionMode? "production": "development"));
|
|
||||||
|
|
||||||
// create a new Restler instance
|
|
||||||
//$rest = new \Luracast\Restler\Restler();
|
|
||||||
$this->rest = new \Maveriks\Extension\Restler($productionMode);
|
|
||||||
// setting flag for multipart to Restler
|
|
||||||
$this->rest->setFlagMultipart($multipart);
|
|
||||||
// setting api version to Restler
|
|
||||||
$this->rest->setAPIVersion($version);
|
|
||||||
// adding $authenticationClass to Restler
|
|
||||||
$this->rest->addAuthenticationClass($authenticationClass, '');
|
$this->rest->addAuthenticationClass($authenticationClass, '');
|
||||||
|
|
||||||
// Setting database connection source
|
|
||||||
list($host, $port) = strpos(DB_HOST, ':') !== false ? explode(':', DB_HOST) : array(DB_HOST, '');
|
|
||||||
$port = empty($port) ? '' : ";port=$port";
|
|
||||||
Services\OAuth2\Server::setDatabaseSource(DB_USER, DB_PASS, DB_ADAPTER.":host=$host;dbname=".DB_NAME.$port);
|
|
||||||
|
|
||||||
// Setting default OAuth Client id, for local PM Web Designer
|
|
||||||
Services\OAuth2\Server::setPmClientId($pmOauthClientId);
|
|
||||||
|
|
||||||
$this->rest->setOverridingFormats('JsonFormat', 'UploadFormat');
|
|
||||||
|
|
||||||
$isPluginRequest = strpos($uri, '/plugin-') !== false ? true : false;
|
$isPluginRequest = strpos($uri, '/plugin-') !== false ? true : false;
|
||||||
|
|
||||||
if ($isPluginRequest) {
|
if ($isPluginRequest) {
|
||||||
@@ -340,6 +352,44 @@ class WebApplication
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function configureRest($workspace, $version, $multipart = false)
|
||||||
|
{
|
||||||
|
// $pmOauthClientId - contains PM Local OAuth Id (Web Designer)
|
||||||
|
$pmOauthClientId = 'x-pm-local-client';
|
||||||
|
|
||||||
|
// Setting current workspace to Api class
|
||||||
|
Services\Api::setWorkspace($workspace);
|
||||||
|
$cacheDir = defined("PATH_C")? PATH_C: sys_get_temp_dir();
|
||||||
|
|
||||||
|
$sysConfig = \System::getSystemConfiguration();
|
||||||
|
|
||||||
|
\Luracast\Restler\Defaults::$cacheDirectory = $cacheDir;
|
||||||
|
$productionMode = false; //(bool) !(isset($sysConfig["service_api_debug"]) && $sysConfig["service_api_debug"]);
|
||||||
|
|
||||||
|
Util\Logger::log("Serving API mode: " . ($productionMode? "production": "development"));
|
||||||
|
|
||||||
|
// create a new Restler instance
|
||||||
|
//$rest = new \Luracast\Restler\Restler();
|
||||||
|
$this->rest = new \Maveriks\Extension\Restler($productionMode);
|
||||||
|
$this->rest->setworkspace($workspace);
|
||||||
|
// setting flag for multipart to Restler
|
||||||
|
$this->rest->setFlagMultipart($multipart);
|
||||||
|
// setting api version to Restler
|
||||||
|
$this->rest->setAPIVersion($version);
|
||||||
|
// adding $authenticationClass to Restler
|
||||||
|
|
||||||
|
// Setting database connection source
|
||||||
|
list($host, $port) = strpos(DB_HOST, ':') !== false ? explode(':', DB_HOST) : array(DB_HOST, '');
|
||||||
|
$port = empty($port) ? '' : ";port=$port";
|
||||||
|
Services\OAuth2\Server::setDatabaseSource(DB_USER, DB_PASS, DB_ADAPTER.":host=$host;dbname=".DB_NAME.$port);
|
||||||
|
|
||||||
|
// Setting default OAuth Client id, for local PM Web Designer
|
||||||
|
Services\OAuth2\Server::setPmClientId($pmOauthClientId);
|
||||||
|
Services\OAuth2\Server::setWorkspace($workspace);
|
||||||
|
|
||||||
|
$this->rest->setOverridingFormats('JsonFormat', 'UploadFormat');
|
||||||
|
}
|
||||||
|
|
||||||
public function parseApiRequestUri()
|
public function parseApiRequestUri()
|
||||||
{
|
{
|
||||||
$url = explode("/", $this->requestUri);
|
$url = explode("/", $this->requestUri);
|
||||||
|
|||||||
118
workflow/engine/controllers/oauth2.php
Normal file
118
workflow/engine/controllers/oauth2.php
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
<?php
|
||||||
|
class Oauth2 extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$http = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
|
||||||
|
$host = $_SERVER['SERVER_NAME'] . ($_SERVER['SERVER_PORT'] != '80' ? ':' . $_SERVER['SERVER_PORT'] : '');
|
||||||
|
|
||||||
|
//$applicationsLink = sprintf('%s://%s/sys%s/%s/%s/oauth2/applications', $http, $host, SYS_SYS, SYS_LANG, SYS_SKIN);
|
||||||
|
$applicationsLink = sprintf('%s://%s/%s/oauth2/apps', $http, $host, SYS_SYS);
|
||||||
|
$authorizationLink = sprintf('%s://%s/%s/oauth2/authorize?response_type=code&client_id=[the-client-id]&scope=*', $http, $host, SYS_SYS);
|
||||||
|
//http://<your-pm-server>/sys<your-workspace>/en/neoclassic/oauth2/authorize?response_type=code&client_id={your-client-d}&scope=view_processes%20edit_processes
|
||||||
|
$this->setVar('applications_link', $applicationsLink);
|
||||||
|
$this->setVar('authorization_link', $authorizationLink);
|
||||||
|
|
||||||
|
$this->setView('oauth2/index');
|
||||||
|
$this->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function apps()
|
||||||
|
{
|
||||||
|
$http = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
|
||||||
|
$host = $_SERVER['SERVER_NAME'] . ($_SERVER['SERVER_PORT'] != '80' ? ':' . $_SERVER['SERVER_PORT'] : '');
|
||||||
|
|
||||||
|
$applicationsLink = sprintf('%s://%s/sys%s/%s/%s/oauth2/applications', $http, $host, SYS_SYS, SYS_LANG, SYS_SKIN);
|
||||||
|
|
||||||
|
header('location: ' . $applicationsLink);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
session_start();
|
||||||
|
if (! isset($_SESSION['USER_LOGGED'])) {
|
||||||
|
$http = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
|
||||||
|
$host = $_SERVER['SERVER_NAME'] . ($_SERVER['SERVER_PORT'] != '80' ? ':' . $_SERVER['SERVER_PORT'] : '');
|
||||||
|
|
||||||
|
$loginLink = sprintf('%s://%s/sys%s/%s/%s/login/login?u=/%s/oauth2/authorize', $http, $host, SYS_SYS, SYS_LANG, SYS_SKIN, SYS_SYS);
|
||||||
|
header('location: ' . $loginLink);
|
||||||
|
die;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($_SERVER['REQUEST_METHOD']) {
|
||||||
|
case 'GET':
|
||||||
|
require_once PATH_CORE . 'src/ProcessMaker/Services/OAuth2/PmPdo.php';
|
||||||
|
|
||||||
|
|
||||||
|
list($host, $port) = strpos(DB_HOST, ':') !== false ? explode(':', DB_HOST) : array(DB_HOST, '');
|
||||||
|
$port = empty($port) ? '' : ";port=$port";
|
||||||
|
|
||||||
|
$dsn = DB_ADAPTER.':host='.$host.';dbname='.DB_NAME.$port;
|
||||||
|
$username = DB_USER;
|
||||||
|
$password = DB_PASS;
|
||||||
|
|
||||||
|
$this->scope = array(
|
||||||
|
'view_processes' => 'View Processes',
|
||||||
|
'edit_processes' => 'Edit Processes'
|
||||||
|
);
|
||||||
|
|
||||||
|
// $dsn is the Data Source Name for your database, for example "mysql:dbname=my_oauth2_db;host=localhost"
|
||||||
|
$storage = new ProcessMaker\Services\OAuth2\PmPdo(array('dsn' => $dsn, 'username' => $username, 'password' => $password));
|
||||||
|
|
||||||
|
$clientId = $_GET['client_id'];
|
||||||
|
$requestedScope = isset($_GET['scope']) ? $_GET['scope'] : '';
|
||||||
|
$requestedScope = empty($requestedScope) ? array() : explode(' ', $requestedScope);
|
||||||
|
|
||||||
|
if (! empty($clientId)) {
|
||||||
|
$client = $storage->getClientDetails($clientId);
|
||||||
|
// throw error, client does not exist.
|
||||||
|
}
|
||||||
|
|
||||||
|
//echo '<pre>';print_r($client); echo '</pre>';
|
||||||
|
|
||||||
|
$client = array('name' => $client['client_name'], 'desc' => $client['client_description']);
|
||||||
|
|
||||||
|
//echo '<pre>';print_r($_SESSION); echo '</pre>'; die;
|
||||||
|
$user = array('name' => $_SESSION['USR_FULLNAME']);
|
||||||
|
|
||||||
|
$this->setVar('user', $user);
|
||||||
|
$this->setVar('client', $client);
|
||||||
|
$this->setVar('postUri', '/' . SYS_SYS . '/oauth2/authorize?' . $_SERVER['QUERY_STRING']);
|
||||||
|
//$this->setVar('postUri', '/' . SYS_SYS . '/oauth2/authorize');
|
||||||
|
//$this->setVar('query_string', $_SERVER['QUERY_STRING']);
|
||||||
|
$this->setView('oauth2/authorize');
|
||||||
|
$this->render();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'POST':
|
||||||
|
require_once PATH_CORE . 'src/ProcessMaker/Services/OAuth2/Server.php';
|
||||||
|
|
||||||
|
list($host, $port) = strpos(DB_HOST, ':') !== false ? explode(':', DB_HOST) : array(DB_HOST, '');
|
||||||
|
$port = empty($port) ? '' : ";port=$port";
|
||||||
|
|
||||||
|
\ProcessMaker\Services\OAuth2\Server::setDatabaseSource(DB_USER, DB_PASS, DB_ADAPTER.":host=$host;dbname=".DB_NAME.$port);
|
||||||
|
\ProcessMaker\Services\OAuth2\Server::setPmClientId('x-pm-local-client');
|
||||||
|
|
||||||
|
$oauthServer = new \ProcessMaker\Services\OAuth2\Server();
|
||||||
|
$userid = $_SESSION['USER_LOGGED'];
|
||||||
|
$authorize = array_key_exists('cancel', $_POST)? false: true;
|
||||||
|
|
||||||
|
|
||||||
|
$response = $oauthServer->postAuthorize($authorize, $userid, true);
|
||||||
|
|
||||||
|
//$code = substr($response->getHttpHeader('Location'), strpos($response->getHttpHeader('Location'), 'code=')+5, 40);
|
||||||
|
|
||||||
|
//echo 'session_id ' . session_id() . '<br>';
|
||||||
|
//exit("SUCCESS! ==> Authorization Code: $code");
|
||||||
|
|
||||||
|
die($response->send());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function token()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ if (! empty($_GET['error'])) {
|
|||||||
|
|
||||||
$http = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
|
$http = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
|
||||||
$host = $_SERVER['SERVER_NAME'] . ($_SERVER['SERVER_PORT'] != '80' ? ':' . $_SERVER['SERVER_PORT'] : '');
|
$host = $_SERVER['SERVER_NAME'] . ($_SERVER['SERVER_PORT'] != '80' ? ':' . $_SERVER['SERVER_PORT'] : '');
|
||||||
$endpoint = sprintf('%s://%s/api/1.0/%s/token', $http, $host, SYS_SYS);
|
$endpoint = sprintf('%s://%s/%s/oauth2/token', $http, $host, SYS_SYS);
|
||||||
$code = empty($_GET['code']) ? 'NN' : $_GET['code'];
|
$code = empty($_GET['code']) ? 'NN' : $_GET['code'];
|
||||||
|
|
||||||
$clientId = 'x-pm-local-client';
|
$clientId = 'x-pm-local-client';
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class PmPdo implements \OAuth2\Storage\AuthorizationCodeInterface,
|
|||||||
'access_token_table' => 'OAUTH_ACCESS_TOKENS',
|
'access_token_table' => 'OAUTH_ACCESS_TOKENS',
|
||||||
'refresh_token_table' => 'OAUTH_REFRESH_TOKENS',
|
'refresh_token_table' => 'OAUTH_REFRESH_TOKENS',
|
||||||
'code_table' => 'OAUTH_AUTHORIZATION_CODES',
|
'code_table' => 'OAUTH_AUTHORIZATION_CODES',
|
||||||
'user_table' => 'OAUTH_USERS',
|
'user_table' => 'USERS',
|
||||||
'jwt_table' => 'OAUTH_JWT',
|
'jwt_table' => 'OAUTH_JWT',
|
||||||
), $config);
|
), $config);
|
||||||
}
|
}
|
||||||
@@ -193,12 +193,12 @@ class PmPdo implements \OAuth2\Storage\AuthorizationCodeInterface,
|
|||||||
// plaintext passwords are bad! Override this for your application
|
// plaintext passwords are bad! Override this for your application
|
||||||
protected function checkPassword($user, $password)
|
protected function checkPassword($user, $password)
|
||||||
{
|
{
|
||||||
return $user['password'] == sha1($password);
|
return $user['USR_PASSWORD'] == md5($password);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getUser($username)
|
public function getUser($username)
|
||||||
{
|
{
|
||||||
$stmt = $this->db->prepare($sql = sprintf('SELECT * FROM %s WHERE USERNAME=:username', $this->config['user_table']));
|
$stmt = $this->db->prepare($sql = sprintf('SELECT * FROM %s WHERE USR_USERNAME=:username', $this->config['user_table']));
|
||||||
$stmt->execute(array('username' => $username));
|
$stmt->execute(array('username' => $username));
|
||||||
|
|
||||||
if (!$userInfo = $stmt->fetch()) {
|
if (!$userInfo = $stmt->fetch()) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
namespace ProcessMaker\Services\OAuth2;
|
namespace ProcessMaker\Services\OAuth2;
|
||||||
|
|
||||||
use Luracast\Restler\iAuthenticate;
|
use Luracast\Restler\iAuthenticate;
|
||||||
|
use Luracast\Restler\RestException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,6 +29,7 @@ class Server implements iAuthenticate
|
|||||||
protected static $dbUser;
|
protected static $dbUser;
|
||||||
protected static $dbPassword;
|
protected static $dbPassword;
|
||||||
protected static $dsn;
|
protected static $dsn;
|
||||||
|
protected static $workspace;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -35,7 +37,8 @@ class Server implements iAuthenticate
|
|||||||
|
|
||||||
$this->scope = array(
|
$this->scope = array(
|
||||||
'view_processes' => 'View Processes',
|
'view_processes' => 'View Processes',
|
||||||
'edit_processes' => 'Edit Processes'
|
'edit_processes' => 'Edit Processes',
|
||||||
|
'*' => '*'
|
||||||
);
|
);
|
||||||
|
|
||||||
// $dsn is the Data Source Name for your database, for exmaple "mysql:dbname=my_oauth2_db;host=localhost"
|
// $dsn is the Data Source Name for your database, for exmaple "mysql:dbname=my_oauth2_db;host=localhost"
|
||||||
@@ -44,7 +47,7 @@ class Server implements iAuthenticate
|
|||||||
$this->storage = new PmPdo($config);
|
$this->storage = new PmPdo($config);
|
||||||
|
|
||||||
// Pass a storage object or array of storage objects to the OAuth2 server class
|
// Pass a storage object or array of storage objects to the OAuth2 server class
|
||||||
$this->server = new \OAuth2\Server($this->storage);
|
$this->server = new \OAuth2\Server($this->storage, array('allow_implicit' => true));
|
||||||
|
|
||||||
$this->server->setConfig('enforce_state', false);
|
$this->server->setConfig('enforce_state', false);
|
||||||
|
|
||||||
@@ -52,14 +55,21 @@ class Server implements iAuthenticate
|
|||||||
$this->server->addGrantType(new \OAuth2\GrantType\AuthorizationCode($this->storage));
|
$this->server->addGrantType(new \OAuth2\GrantType\AuthorizationCode($this->storage));
|
||||||
|
|
||||||
// Add the "Client Credentials" grant type (it is the simplest of the grant types)
|
// Add the "Client Credentials" grant type (it is the simplest of the grant types)
|
||||||
//$this->server->addGrantType(new \OAuth2\GrantType\ClientCredentials($this->storage));
|
$this->server->addGrantType(new \OAuth2\GrantType\ClientCredentials($this->storage));
|
||||||
|
|
||||||
// Add the "Refresh token" grant type
|
// Add the "Refresh token" grant type
|
||||||
$this->server->addGrantType(new \OAuth2\GrantType\RefreshToken($this->storage));
|
$this->server->addGrantType(new \OAuth2\GrantType\RefreshToken($this->storage));
|
||||||
|
|
||||||
$scope = new \OAuth2\Scope(array(
|
// create some users in memory
|
||||||
'supported_scopes' => array_keys($this->scope)
|
//$users = array('bshaffer' => array('password' => 'brent123', 'first_name' => 'Brent', 'last_name' => 'Shaffer'));
|
||||||
));
|
// create a storage object
|
||||||
|
//$storage = new \OAuth2\Storage\Memory(array('user_credentials' => $users));
|
||||||
|
// create the grant type
|
||||||
|
$grantType = new \OAuth2\GrantType\UserCredentials($this->storage);
|
||||||
|
// add the grant type to your OAuth server
|
||||||
|
$this->server->addGrantType($grantType);
|
||||||
|
|
||||||
|
$scope = new \OAuth2\Scope(array('supported_scopes' => array_keys($this->scope)));
|
||||||
$this->server->setScopeUtil($scope);
|
$this->server->setScopeUtil($scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,6 +86,28 @@ class Server implements iAuthenticate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function setWorkspace($workspace)
|
||||||
|
{
|
||||||
|
self::$workspace = $workspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$http = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
|
||||||
|
$host = $_SERVER['SERVER_NAME'] . ($_SERVER['SERVER_PORT'] != '80' ? ':' . $_SERVER['SERVER_PORT'] : '');
|
||||||
|
$host = $http .'://'. $host;
|
||||||
|
|
||||||
|
$applicationsLink = sprintf('%s/%s/oauth2/apps', $host, SYS_SYS);
|
||||||
|
$authorizationLink = sprintf('%s/%s/oauth2/authorize?response_type=code&client_id=[the-client-id]&scope=*', $host, SYS_SYS);
|
||||||
|
|
||||||
|
$view = new \Maveriks\Pattern\Mvc\SmartyView(PATH_CORE . "templates/oauth2/index.html");
|
||||||
|
$view->assign('host', $host);
|
||||||
|
$view->assign('workspace', self::$workspace);
|
||||||
|
|
||||||
|
$view->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @view oauth2/server/register.php
|
* @view oauth2/server/register.php
|
||||||
* @format HtmlFormat
|
* @format HtmlFormat
|
||||||
@@ -91,25 +123,53 @@ class Server implements iAuthenticate
|
|||||||
*
|
*
|
||||||
* User responds by accepting or denying
|
* User responds by accepting or denying
|
||||||
*
|
*
|
||||||
* @view oauth2/server/authorize.php
|
|
||||||
* @format HtmlFormat
|
|
||||||
*/
|
*/
|
||||||
public function authorize()
|
public function authorize()
|
||||||
{
|
{
|
||||||
$clientId = \OAuth2\Request::createFromGlobals()->query('client_id', '');
|
session_start();
|
||||||
$requestedScope = \OAuth2\Request::createFromGlobals()->query('scope', '');
|
|
||||||
$requestedScope = empty($requestedScope) ? array() : explode(' ', $requestedScope);
|
|
||||||
|
|
||||||
if (! empty($clientId)) {
|
if (! isset($_SESSION['USER_LOGGED'])) {
|
||||||
$clientDetails = $this->storage->getClientDetails(\OAuth2\Request::createFromGlobals()->query('client_id'));
|
$http = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';
|
||||||
|
$host = $http . '://' . $_SERVER['SERVER_NAME'] . ($_SERVER['SERVER_PORT'] != '80' ? ':' . $_SERVER['SERVER_PORT'] : '');
|
||||||
|
$redirect = urlencode($host.'/'.self::$workspace.$_SERVER['REQUEST_URI']);
|
||||||
|
|
||||||
|
$loginLink = sprintf('%s/sys%s/%s/%s/login/login?u=%s', $host, SYS_SYS, SYS_LANG, SYS_SKIN, $redirect);
|
||||||
|
header('location: ' . $loginLink);
|
||||||
|
die;
|
||||||
}
|
}
|
||||||
|
|
||||||
return array(
|
$this->scope = array(
|
||||||
'client_details' => $clientDetails,
|
'view_processes' => 'View Processes',
|
||||||
'query_string' => $_SERVER['QUERY_STRING'],
|
'edit_processes' => 'Edit Processes'
|
||||||
'supportedScope' => $this->scope,
|
|
||||||
'requestedScope' => $requestedScope
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (! array_key_exists('client_id', $_GET)) {
|
||||||
|
throw new RestException(400, "Invalid request. The 'client_id' parameter is missing!");
|
||||||
|
}
|
||||||
|
if (! array_key_exists('response_type', $_GET)) {
|
||||||
|
throw new RestException(400, "Invalid request. The 'response_type' parameter is missing!");
|
||||||
|
}
|
||||||
|
|
||||||
|
$clientId = $_GET['client_id'];
|
||||||
|
$requestedScope = isset($_GET['scope']) ? $_GET['scope'] : '*';
|
||||||
|
$requestedScope = empty($requestedScope) ? array() : explode(' ', $requestedScope);
|
||||||
|
$client = $this->storage->getClientDetails($clientId);;
|
||||||
|
|
||||||
|
if (empty($client)) {
|
||||||
|
// throw error, client does not exist.
|
||||||
|
throw new RestException(400, "Error, unknown client. The client with id '".$clientId."' is not registered");
|
||||||
|
}
|
||||||
|
|
||||||
|
//echo '<pre>';print_r($client); echo '</pre>'; die;
|
||||||
|
$client = array('name' => $client['client_name'], 'desc' => $client['client_description']);
|
||||||
|
$user = array('name' => $_SESSION['USR_FULLNAME']);
|
||||||
|
|
||||||
|
$view = new \Maveriks\Pattern\Mvc\SmartyView(PATH_CORE . "templates/oauth2/authorize.html");
|
||||||
|
$view->assign('user', $user);
|
||||||
|
$view->assign('client', $client);
|
||||||
|
$view->assign('postUri', '/' . SYS_SYS . '/oauth2/authorize?' . $_SERVER['QUERY_STRING']);
|
||||||
|
$view->render();
|
||||||
|
exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -120,15 +180,19 @@ class Server implements iAuthenticate
|
|||||||
*
|
*
|
||||||
* On success authorization code is sent along
|
* On success authorization code is sent along
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* @param bool $authorize
|
|
||||||
* @param string $userId optional user id
|
|
||||||
* @param bool $returnResponse optional flag to specify if the function should return the Response object
|
|
||||||
* @return \OAuth2\ResponseInterface
|
|
||||||
* @format JsonFormat,UploadFormat
|
* @format JsonFormat,UploadFormat
|
||||||
*/
|
*/
|
||||||
public function postAuthorize($authorize = false, $userId = null, $returnResponse = false)
|
public function postAuthorize()
|
||||||
{
|
{
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
if (! isset($_SESSION['USER_LOGGED'])) {
|
||||||
|
throw new RestException(400, "Local Authentication Error, user session is not started.");
|
||||||
|
}
|
||||||
|
|
||||||
|
$userId = $_SESSION['USER_LOGGED'];
|
||||||
|
$authorize = array_key_exists('cancel', $_REQUEST)? false: true;
|
||||||
|
|
||||||
$request = \OAuth2\Request::createFromGlobals();
|
$request = \OAuth2\Request::createFromGlobals();
|
||||||
$response = new \OAuth2\Response();
|
$response = new \OAuth2\Response();
|
||||||
|
|
||||||
@@ -139,10 +203,6 @@ class Server implements iAuthenticate
|
|||||||
$userId
|
$userId
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($returnResponse) {
|
|
||||||
return $response;
|
|
||||||
}
|
|
||||||
|
|
||||||
die($response->send());
|
die($response->send());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
52
workflow/engine/templates/oauth2/authorize.html
Normal file
52
workflow/engine/templates/oauth2/authorize.html
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>ProcessMaker Oauth2 Server</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
|
||||||
|
<!-- Style sheets -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="/assets/css/pure-min.css">
|
||||||
|
<link rel="stylesheet" href="/assets/css/base-min.css">
|
||||||
|
<link rel="stylesheet" type="text/css" href="/assets/css/grids-responsive-min.css">
|
||||||
|
<script type="text/javascript" src="/assets/js/jquery.min.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/assets/css/oauth2.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<form action="{$postUri}" method="post" class="pure-form pure-form-stacked" enctype="application/x-www-form-urlencoded">
|
||||||
|
<input name="transaction_id" type="hidden" value="{$transactionID}">
|
||||||
|
<fieldset>
|
||||||
|
<!-- Upper box with Title, username, and password -->
|
||||||
|
<div class="upper-box">
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<div style="padding-top: 15px">
|
||||||
|
<img style="display: block; margin-left: auto; margin-right: auto;" src="/images/processmaker.logo.jpg">
|
||||||
|
<div class="subtext">Authorization Server</div>
|
||||||
|
</div>
|
||||||
|
<div class="pure-control-group labels">
|
||||||
|
<p>
|
||||||
|
<p>{$user.name},</p>
|
||||||
|
The application <b>{$client.name}</b> is requesting access to your account.
|
||||||
|
|
||||||
|
<h4>{$client.client_name}</h4>
|
||||||
|
<small><i>{$client.desc}</i></small>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Do you approve?</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Bottom box with Sign in -->
|
||||||
|
<div class="bottom-box">
|
||||||
|
<div class="pure-controls accept-cancel-buttons">
|
||||||
|
<div>
|
||||||
|
<input class="pure-button pure-button-primary" type="submit" value="Accept" id="allow">
|
||||||
|
<!-- Cheat to make a bit of spacing -->
|
||||||
|
<span>  </span>
|
||||||
|
<input class="pure-button" type="submit" value="Deny" name="cancel" id="deny">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
</form>
|
||||||
210
workflow/engine/templates/oauth2/index.html
Normal file
210
workflow/engine/templates/oauth2/index.html
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>ProcessMaker Oauth2 Server</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
|
||||||
|
<!-- Style sheets -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="/assets/css/pure-min.css">
|
||||||
|
<link rel="stylesheet" href="/assets/css/base-min.css">
|
||||||
|
<link rel="stylesheet" type="text/css" href="/assets/css/grids-responsive-min.css">
|
||||||
|
<script type="text/javascript" src="/assets/js/jquery.min.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/assets/css/oauth2.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="layout" class="pure-g">
|
||||||
|
<div class="sidebar pure-u-1 pure-u-md-1-4">
|
||||||
|
<div class="header">
|
||||||
|
<hgroup>
|
||||||
|
<h2 class="brand-title">ProcessMaker</h2>
|
||||||
|
<h3 class="brand-tagline">Authorization Server</h3>
|
||||||
|
<h4 class="brand-tagline">OAuth v2</h4>
|
||||||
|
</hgroup>
|
||||||
|
|
||||||
|
<!--<nav class="nav">
|
||||||
|
<ul class="nav-list">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="pure-button" href="#">AAA</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="pure-button" href="#">BBB</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content pure-u-1 pure-u-md-3-4">
|
||||||
|
<div>
|
||||||
|
<!-- A wrapper for all the blog posts -->
|
||||||
|
<div class="posts">
|
||||||
|
<h1 class="content-subhead">Authorization Code</h1>
|
||||||
|
<section class="post">
|
||||||
|
<header class="post-header">
|
||||||
|
<h2 class="post-title">Authorization Code</h2>
|
||||||
|
|
||||||
|
<p class="post-meta">
|
||||||
|
See RFC <a href="http://tools.ietf.org/html/rfc6749#section-4.1" target="_blank" class="post-author">Authorization Code Grant</a>
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="post-description">
|
||||||
|
<p>
|
||||||
|
The authorization code grant type is used to obtain both access tokens and refresh tokens and is optimized for
|
||||||
|
confidential clients.<br/>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
Register the application
|
||||||
|
<pre>
|
||||||
|
GET {$host}/{$workspace}/oauth2/apps</pre>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Request Authorization
|
||||||
|
<pre>
|
||||||
|
GET {$host}/{$workspace}/oauth2/authorize?response_type=code&client_id={literal}{the-client-id}{/literal}&scope=*</pre>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Exchange Authorization code by an Access Token.
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
POST {$host}/{$workspace}/oauth2/token
|
||||||
|
Authorization: Basic eC1wbS1sb2NhbC1jbGllbnQ6MTc5YWQ0NWM2Y2UyY2I5N2NmMTAyOWUyMTIwNDZlODE=
|
||||||
|
|
||||||
|
grant_type=code&
|
||||||
|
code={literal}{the-authorization-code}{/literal}
|
||||||
|
</pre>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
<p><a id="authcode" href="{$auth_code_link}">{$auth_code_link}</a></p>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<h1 class="content-subhead">Implicit Grant</h1>
|
||||||
|
<section class="post">
|
||||||
|
<header class="post-header">
|
||||||
|
<h2 class="post-title">Implicit Grant</h2>
|
||||||
|
|
||||||
|
<p class="post-meta">
|
||||||
|
See RFC <a href="http://tools.ietf.org/html/rfc6749#section-4.2" target="_blank" class="post-author">Implicit Grant</a>
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="post-description">
|
||||||
|
<p>
|
||||||
|
The implicit grant type is used to obtain access tokens (it does not support the issuance of refresh tokens) and
|
||||||
|
is optimized for public clients known to operate a particular redirection URI.
|
||||||
|
|
||||||
|
<pre>GET {$host}/{$workspace}/oauth2/authorize?response_type=token&client_id={literal}{the-client-id}{/literal}&scope=*</pre>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<h1 class="content-subhead">Resource Owner Password Credentials</h1>
|
||||||
|
<section class="post">
|
||||||
|
<header class="post-header">
|
||||||
|
<h2 class="post-title">Resource Owner Password Credentials</h2>
|
||||||
|
|
||||||
|
<p class="post-meta">
|
||||||
|
See RFC <a href="http://tools.ietf.org/html/rfc6749#section-4.3" target="_blank" class="post-author">Resource Owner Password Credentials</a>
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="post-description">
|
||||||
|
<p>
|
||||||
|
The resource owner password credentials grant type is suitable in cases where the resource owner has a trust
|
||||||
|
relationship with the client, such as the device operating system or a highly privileged application.<br/><br/>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
POST {$host}/{$workspace}/oauth2/token
|
||||||
|
Content-Type: application/x-www-form-urlencoded
|
||||||
|
Authorization: Basic eC1wbS1sb2NhbC1jbGllbnQ6MTc5YWQ0NWM2Y2UyY2I5N2NmMTAyOWUyMTIwNDZlODE=
|
||||||
|
|
||||||
|
grant_type=password&
|
||||||
|
username=bob&
|
||||||
|
password=secret&
|
||||||
|
scope=offline_access
|
||||||
|
</pre>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<h1 class="content-subhead">Client Credentials</h1>
|
||||||
|
<section class="post">
|
||||||
|
<header class="post-header">
|
||||||
|
<h2 class="post-title">Client Credentials</h2>
|
||||||
|
|
||||||
|
<p class="post-meta">
|
||||||
|
See RFC <a href="http://tools.ietf.org/html/rfc6749#section-4.4" target="_blank" class="post-author">Client Credentials</a>
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="post-description">
|
||||||
|
<p>
|
||||||
|
The client can request an access token using only its client credentials (or other supported means of authentication)
|
||||||
|
when the client is requesting access to the protected resources under its control, or those of another resource
|
||||||
|
owner that have been previously arranged with the authorization server. <br/><br/>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
POST {$host}/{$workspace}/oauth/2/token
|
||||||
|
Content-Type: application/x-www-form-urlencoded
|
||||||
|
Authorization: Basic eC1wbS1sb2NhbC1jbGllbnQ6MTc5YWQ0NWM2Y2UyY2I5N2NmMTAyOWUyMTIwNDZlODE=
|
||||||
|
|
||||||
|
grant_type=client_credentials
|
||||||
|
</pre>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<h1 class="content-subhead">Refresh Token</h1>
|
||||||
|
<section class="post">
|
||||||
|
<header class="post-header">
|
||||||
|
<h2 class="post-title">Refresh Token</h2>
|
||||||
|
|
||||||
|
<p class="post-meta">
|
||||||
|
See RFC <a href="http://tools.ietf.org/html/rfc6749#section-1.5" target="_blank" class="post-author">Refresh Token</a>
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="post-description">
|
||||||
|
<p>
|
||||||
|
Refresh tokens are credentials used to obtain access tokens. Refresh
|
||||||
|
tokens are issued to the client by the authorization server and are
|
||||||
|
used to obtain a new access token when the current access token
|
||||||
|
becomes invalid or expires, or to obtain additional access tokens
|
||||||
|
with identical or narrower scope (access tokens may have a shorter
|
||||||
|
lifetime and fewer permissions than authorized by the resource
|
||||||
|
owner). Issuing a refresh token is optional at the discretion of the
|
||||||
|
authorization server. If the authorization server issues a refresh
|
||||||
|
token, it is included when issuing an access token. <br/><br/>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
POST {$host}/{$workspace}/oauth2/token
|
||||||
|
Content-Type: application/x-www-form-urlencoded
|
||||||
|
Authorization: Basic eC1wbS1sb2NhbC1jbGllbnQ6MTc5YWQ0NWM2Y2UyY2I5N2NmMTAyOWUyMTIwNDZlODE=
|
||||||
|
|
||||||
|
grant_type=refresh_token
|
||||||
|
refresh_token={literal}{your-refresh-token}{/literal}
|
||||||
|
</pre>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
<div class="pure-menu pure-menu-horizontal pure-menu-open">
|
||||||
|
<ul>
|
||||||
|
<li><a href="http://processmaker.com/">ProcessMaker</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
11
workflow/public_html/assets/css/base-min.css
vendored
Normal file
11
workflow/public_html/assets/css/base-min.css
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/*!
|
||||||
|
Pure v0.5.0
|
||||||
|
Copyright 2014 Yahoo! Inc. All rights reserved.
|
||||||
|
Licensed under the BSD License.
|
||||||
|
https://github.com/yui/pure/blob/master/LICENSE.md
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
normalize.css v1.1.3 | MIT License | git.io/normalize
|
||||||
|
Copyright (c) Nicolas Gallagher and Jonathan Neal
|
||||||
|
*/
|
||||||
|
/*! normalize.css v1.1.3 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none;height:0}[hidden]{display:none}html{font-size:100%;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}html,button,input,select,textarea{font-family:sans-serif}body{margin:0}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{font-size:2em;margin:.67em 0}h2{font-size:1.5em;margin:.83em 0}h3{font-size:1.17em;margin:1em 0}h4{font-size:1em;margin:1.33em 0}h5{font-size:.83em;margin:1.67em 0}h6{font-size:.67em;margin:2.33em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:1em 40px}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}p,pre{margin:1em 0}code,kbd,pre,samp{font-family:monospace,serif;_font-family:'courier new',monospace;font-size:1em}pre{white-space:pre;white-space:pre-wrap;word-wrap:break-word}q{quotes:none}q:before,q:after{content:'';content:none}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,menu,ol,ul{margin:1em 0}dd{margin:0 0 0 40px}menu,ol,ul{padding:0 0 0 40px}nav ul,nav ol{list-style:none;list-style-image:none}img{border:0;-ms-interpolation-mode:bicubic}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0;white-space:normal;*margin-left:-7px}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;*overflow:visible}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0;*height:13px;*width:13px}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}[hidden]{display:none!important}.pure-img{max-width:100%;height:auto;display:block}
|
||||||
197
workflow/public_html/assets/css/dialog-modules.css
Normal file
197
workflow/public_html/assets/css/dialog-modules.css
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
/**
|
||||||
|
* Coloring h1 a bit off black, removing bold, and shadowing
|
||||||
|
* a touch.
|
||||||
|
*/
|
||||||
|
h1 {
|
||||||
|
color: #505050;
|
||||||
|
text-shadow: 2px 1px 3px rgba(200, 200, 200, 0.43);
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Using some off white for the background color and
|
||||||
|
* padding the top.
|
||||||
|
*/
|
||||||
|
body
|
||||||
|
{
|
||||||
|
background: whitesmoke;
|
||||||
|
padding-top: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make links smaller,
|
||||||
|
*/
|
||||||
|
a
|
||||||
|
{
|
||||||
|
text-shadow: 2px 1px 3px rgba(200, 200, 200, 0.43);
|
||||||
|
padding-bottom: 5px;
|
||||||
|
padding-top: 10px;
|
||||||
|
font-size: 80%;
|
||||||
|
color: #6464ff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre
|
||||||
|
{
|
||||||
|
margin-top: 0px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
width: 500px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upper box that contains the title Authorization Server, the UserName, and Password fields
|
||||||
|
*/
|
||||||
|
.upper-box {
|
||||||
|
|
||||||
|
width: 350px;
|
||||||
|
|
||||||
|
border-top: 1px solid;
|
||||||
|
border-left: 1px solid;
|
||||||
|
border-right: 1px solid;
|
||||||
|
|
||||||
|
border-color: lightgrey;
|
||||||
|
border-top-left-radius: 3px;
|
||||||
|
border-top-right-radius: 3px;
|
||||||
|
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
|
||||||
|
box-shadow: 1px 1px 5px #e7e7e7;
|
||||||
|
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gradient calculated from gradient calculator of
|
||||||
|
* http://gradients.glrzad.com/
|
||||||
|
*/
|
||||||
|
background-image: linear-gradient(bottom, rgb(249,250,252) 21%, rgb(245,247,250) 67%, rgb(247,249,255) 94%);
|
||||||
|
background-image: -o-linear-gradient(bottom, rgb(249,250,252) 21%, rgb(245,247,250) 67%, rgb(247,249,255) 94%);
|
||||||
|
background-image: -moz-linear-gradient(bottom, rgb(249,250,252) 21%, rgb(245,247,250) 67%, rgb(247,249,255) 94%);
|
||||||
|
background-image: -webkit-linear-gradient(bottom, rgb(249,250,252) 21%, rgb(245,247,250) 67%, rgb(247,249,255) 94%);
|
||||||
|
background-image: -ms-linear-gradient(bottom, rgb(249,250,252) 21%, rgb(245,247,250) 67%, rgb(247,249,255) 94%);
|
||||||
|
|
||||||
|
background-image: -webkit-gradient(
|
||||||
|
linear,
|
||||||
|
left bottom,
|
||||||
|
left top,
|
||||||
|
color-stop(0.21, rgb(249,250,252)),
|
||||||
|
color-stop(0.67, rgb(245,247,250)),
|
||||||
|
color-stop(0.94, rgb(247,249,255))
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bottom box that contains the "Sign in" button
|
||||||
|
*/
|
||||||
|
.bottom-box {
|
||||||
|
border:1px solid;
|
||||||
|
border-color: lightgrey;
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
|
||||||
|
width: 350px;
|
||||||
|
padding-top: 15px;
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
box-shadow: 1px 3px 1px #e7e7e7;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gradient calculated from gradient calculator of
|
||||||
|
* http://gradients.glrzad.com/
|
||||||
|
*/
|
||||||
|
background-image: linear-gradient(bottom, rgb(242,245,250) 21%, rgb(242,245,250) 67%, rgb(242,245,255) 94%);
|
||||||
|
background-image: -o-linear-gradient(bottom, rgb(242,245,250) 21%, rgb(242,245,250) 67%, rgb(242,245,255) 94%);
|
||||||
|
background-image: -moz-linear-gradient(bottom, rgb(242,245,250) 21%, rgb(242,245,250) 67%, rgb(242,245,255) 94%);
|
||||||
|
background-image: -webkit-linear-gradient(bottom, rgb(242,245,250) 21%, rgb(242,245,250) 67%, rgb(242,245,255) 94%);
|
||||||
|
background-image: -ms-linear-gradient(bottom, rgb(242,245,250) 21%, rgb(242,245,250) 67%, rgb(242,245,255) 94%);
|
||||||
|
|
||||||
|
background-image: -webkit-gradient(
|
||||||
|
linear,
|
||||||
|
left bottom,
|
||||||
|
left top,
|
||||||
|
color-stop(0.21, rgb(242,245,250)),
|
||||||
|
color-stop(0.67, rgb(242,245,250)),
|
||||||
|
color-stop(0.94, rgb(242,245,255))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Okay, you caught me. It's a hack to make this look centered.
|
||||||
|
*
|
||||||
|
* TODO Fix this, can't figure out how to get this to center correctly.
|
||||||
|
* It's currently anchored to the fieldset and that's causing issues.
|
||||||
|
*/
|
||||||
|
.main-text {
|
||||||
|
padding-left: 100px;
|
||||||
|
padding-top: 20px;
|
||||||
|
font-size: 180%;
|
||||||
|
color: #505050;
|
||||||
|
text-shadow: 2px 1px 3px rgba(200, 200, 200, 0.43);
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Okay, you caught me. It's a hack to make this look centered.
|
||||||
|
*
|
||||||
|
* TODO Fix this, can't figure out how to get this to center correctly.
|
||||||
|
* It's currently anchored to the fieldset and that's causing issues.
|
||||||
|
*/
|
||||||
|
.subtext {
|
||||||
|
padding-left: 80px;
|
||||||
|
font-size: 110%;
|
||||||
|
color: #969696;
|
||||||
|
text-shadow: 2px 1px 3px rgba(230, 230, 230, 0.42);
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The username and password labels
|
||||||
|
*/
|
||||||
|
.labels {
|
||||||
|
color: #505050;
|
||||||
|
text-shadow: 2px 1px 3px rgba(200, 200, 200, 0.43);
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input fields so I can make it slightly larger than the default,
|
||||||
|
* and I can also pad anything trying to touch it on the right.
|
||||||
|
*/
|
||||||
|
.input-fields {
|
||||||
|
padding-right: 20px;
|
||||||
|
font-size: 130%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This makes all the placeholder text italic. Nice trick I
|
||||||
|
* picked up from stack overflow:
|
||||||
|
* http://stackoverflow.com/questions/16291925/how-to-make-value-text-in-form-be-italic
|
||||||
|
*/
|
||||||
|
::-webkit-input-placeholder { font-style: italic; }
|
||||||
|
::-moz-placeholder { font-style: italic; }
|
||||||
|
:-ms-input-placeholder { font-style: italic; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Very specific to the sign on button.
|
||||||
|
*/
|
||||||
|
.accept-cancel-buttons {
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 20px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.from-text {
|
||||||
|
padding-top: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
7
workflow/public_html/assets/css/grids-responsive-min.css
vendored
Normal file
7
workflow/public_html/assets/css/grids-responsive-min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
368
workflow/public_html/assets/css/oauth2.css
Normal file
368
workflow/public_html/assets/css/oauth2.css
Normal file
@@ -0,0 +1,368 @@
|
|||||||
|
* {
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: rgb(61, 146, 201);
|
||||||
|
}
|
||||||
|
a:hover,
|
||||||
|
a:focus {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-weight: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LAYOUT CSS */
|
||||||
|
.pure-img-responsive {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layout {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
text-align: center;
|
||||||
|
top: auto;
|
||||||
|
margin: 3em auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
background: rgb(61, 79, 93);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brand-title,
|
||||||
|
.brand-tagline {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.brand-title {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
.brand-tagline {
|
||||||
|
font-weight: 300;
|
||||||
|
color: rgb(176, 202, 219);
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-list {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
.nav-item {
|
||||||
|
display: inline-block;
|
||||||
|
*display: inline;
|
||||||
|
zoom: 1;
|
||||||
|
}
|
||||||
|
.nav-item a {
|
||||||
|
background: transparent;
|
||||||
|
border: 2px solid rgb(176, 202, 219);
|
||||||
|
color: #fff;
|
||||||
|
margin-top: 1em;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 85%;
|
||||||
|
}
|
||||||
|
.nav-item a:hover,
|
||||||
|
.nav-item a:focus {
|
||||||
|
border: 2px solid rgb(61, 146, 201);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-subhead {
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: #aaa;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
padding: 0.4em 0;
|
||||||
|
font-size: 80%;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 2em 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post {
|
||||||
|
padding-bottom: 2em;
|
||||||
|
}
|
||||||
|
.post-title {
|
||||||
|
font-size: 2em;
|
||||||
|
color: #222;
|
||||||
|
margin-bottom: 0.2em;
|
||||||
|
}
|
||||||
|
.post-avatar {
|
||||||
|
border-radius: 50px;
|
||||||
|
float: right;
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
.post-description {
|
||||||
|
font-family: Georgia, "Cambria", serif;
|
||||||
|
color: #444;
|
||||||
|
line-height: 1.8em;
|
||||||
|
}
|
||||||
|
.post-meta {
|
||||||
|
color: #999;
|
||||||
|
font-size: 90%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-category {
|
||||||
|
margin: 0 0.1em;
|
||||||
|
padding: 0.3em 1em;
|
||||||
|
color: #fff;
|
||||||
|
background: #999;
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
.post-category-design {
|
||||||
|
background: #5aba59;
|
||||||
|
}
|
||||||
|
.post-category-pure {
|
||||||
|
background: #4d85d1;
|
||||||
|
}
|
||||||
|
.post-category-yui {
|
||||||
|
background: #8156a7;
|
||||||
|
}
|
||||||
|
.post-category-js {
|
||||||
|
background: #df2d4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-images {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
.post-image-meta {
|
||||||
|
margin-top: -3.5em;
|
||||||
|
margin-left: 1em;
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: 0 1px 1px #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
text-align: center;
|
||||||
|
padding: 1em 0;
|
||||||
|
}
|
||||||
|
.footer a {
|
||||||
|
color: #ccc;
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
.footer .pure-menu a:hover,
|
||||||
|
.footer .pure-menu a:focus {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 48em) {
|
||||||
|
.content {
|
||||||
|
padding: 2em 3em 0;
|
||||||
|
margin-left: 25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
margin: 80% 2em 0;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Coloring h1 a bit off black, removing bold, and shadowing
|
||||||
|
* a touch.
|
||||||
|
*/
|
||||||
|
h1 {
|
||||||
|
color: #505050;
|
||||||
|
text-shadow: 2px 1px 3px rgba(200, 200, 200, 0.43);
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Using some off white for the background color and
|
||||||
|
* padding the top.
|
||||||
|
*/
|
||||||
|
body
|
||||||
|
{
|
||||||
|
background: whitesmoke;
|
||||||
|
padding-top: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make links smaller,
|
||||||
|
*/
|
||||||
|
|
||||||
|
pre
|
||||||
|
{
|
||||||
|
margin-top: 0px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
width: 500px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upper box that contains the title Authorization Server, the UserName, and Password fields
|
||||||
|
*/
|
||||||
|
.upper-box {
|
||||||
|
|
||||||
|
width: 350px;
|
||||||
|
|
||||||
|
border-top: 1px solid;
|
||||||
|
border-left: 1px solid;
|
||||||
|
border-right: 1px solid;
|
||||||
|
|
||||||
|
border-color: lightgrey;
|
||||||
|
border-top-left-radius: 3px;
|
||||||
|
border-top-right-radius: 3px;
|
||||||
|
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
|
||||||
|
box-shadow: 1px 1px 5px #e7e7e7;
|
||||||
|
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gradient calculated from gradient calculator of
|
||||||
|
* http://gradients.glrzad.com/
|
||||||
|
*/
|
||||||
|
background-image: linear-gradient(bottom, rgb(249,250,252) 21%, rgb(245,247,250) 67%, rgb(247,249,255) 94%);
|
||||||
|
background-image: -o-linear-gradient(bottom, rgb(249,250,252) 21%, rgb(245,247,250) 67%, rgb(247,249,255) 94%);
|
||||||
|
background-image: -moz-linear-gradient(bottom, rgb(249,250,252) 21%, rgb(245,247,250) 67%, rgb(247,249,255) 94%);
|
||||||
|
background-image: -webkit-linear-gradient(bottom, rgb(249,250,252) 21%, rgb(245,247,250) 67%, rgb(247,249,255) 94%);
|
||||||
|
background-image: -ms-linear-gradient(bottom, rgb(249,250,252) 21%, rgb(245,247,250) 67%, rgb(247,249,255) 94%);
|
||||||
|
|
||||||
|
background-image: -webkit-gradient(
|
||||||
|
linear,
|
||||||
|
left bottom,
|
||||||
|
left top,
|
||||||
|
color-stop(0.21, rgb(249,250,252)),
|
||||||
|
color-stop(0.67, rgb(245,247,250)),
|
||||||
|
color-stop(0.94, rgb(247,249,255))
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bottom box that contains the "Sign in" button
|
||||||
|
*/
|
||||||
|
.bottom-box {
|
||||||
|
border:1px solid;
|
||||||
|
border-color: lightgrey;
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
|
||||||
|
width: 350px;
|
||||||
|
padding-top: 15px;
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
box-shadow: 1px 3px 1px #e7e7e7;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gradient calculated from gradient calculator of
|
||||||
|
* http://gradients.glrzad.com/
|
||||||
|
*/
|
||||||
|
background-image: linear-gradient(bottom, rgb(242,245,250) 21%, rgb(242,245,250) 67%, rgb(242,245,255) 94%);
|
||||||
|
background-image: -o-linear-gradient(bottom, rgb(242,245,250) 21%, rgb(242,245,250) 67%, rgb(242,245,255) 94%);
|
||||||
|
background-image: -moz-linear-gradient(bottom, rgb(242,245,250) 21%, rgb(242,245,250) 67%, rgb(242,245,255) 94%);
|
||||||
|
background-image: -webkit-linear-gradient(bottom, rgb(242,245,250) 21%, rgb(242,245,250) 67%, rgb(242,245,255) 94%);
|
||||||
|
background-image: -ms-linear-gradient(bottom, rgb(242,245,250) 21%, rgb(242,245,250) 67%, rgb(242,245,255) 94%);
|
||||||
|
|
||||||
|
background-image: -webkit-gradient(
|
||||||
|
linear,
|
||||||
|
left bottom,
|
||||||
|
left top,
|
||||||
|
color-stop(0.21, rgb(242,245,250)),
|
||||||
|
color-stop(0.67, rgb(242,245,250)),
|
||||||
|
color-stop(0.94, rgb(242,245,255))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Okay, you caught me. It's a hack to make this look centered.
|
||||||
|
*
|
||||||
|
* TODO Fix this, can't figure out how to get this to center correctly.
|
||||||
|
* It's currently anchored to the fieldset and that's causing issues.
|
||||||
|
*/
|
||||||
|
.main-text {
|
||||||
|
padding-left: 100px;
|
||||||
|
padding-top: 20px;
|
||||||
|
font-size: 180%;
|
||||||
|
color: #505050;
|
||||||
|
text-shadow: 2px 1px 3px rgba(200, 200, 200, 0.43);
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Okay, you caught me. It's a hack to make this look centered.
|
||||||
|
*
|
||||||
|
* TODO Fix this, can't figure out how to get this to center correctly.
|
||||||
|
* It's currently anchored to the fieldset and that's causing issues.
|
||||||
|
*/
|
||||||
|
.subtext {
|
||||||
|
padding-left: 80px;
|
||||||
|
font-size: 110%;
|
||||||
|
color: #969696;
|
||||||
|
text-shadow: 2px 1px 3px rgba(230, 230, 230, 0.42);
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The username and password labels
|
||||||
|
*/
|
||||||
|
.labels {
|
||||||
|
color: #505050;
|
||||||
|
text-shadow: 2px 1px 3px rgba(200, 200, 200, 0.43);
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input fields so I can make it slightly larger than the default,
|
||||||
|
* and I can also pad anything trying to touch it on the right.
|
||||||
|
*/
|
||||||
|
.input-fields {
|
||||||
|
padding-right: 20px;
|
||||||
|
font-size: 130%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This makes all the placeholder text italic. Nice trick I
|
||||||
|
* picked up from stack overflow:
|
||||||
|
* http://stackoverflow.com/questions/16291925/how-to-make-value-text-in-form-be-italic
|
||||||
|
*/
|
||||||
|
::-webkit-input-placeholder { font-style: italic; }
|
||||||
|
::-moz-placeholder { font-style: italic; }
|
||||||
|
:-ms-input-placeholder { font-style: italic; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Very specific to the sign on button.
|
||||||
|
*/
|
||||||
|
.accept-cancel-buttons {
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 20px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.from-text {
|
||||||
|
padding-top: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
11
workflow/public_html/assets/css/pure-min.css
vendored
Normal file
11
workflow/public_html/assets/css/pure-min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
174
workflow/public_html/assets/css/sign-in-modules.css
Normal file
174
workflow/public_html/assets/css/sign-in-modules.css
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
/**
|
||||||
|
* Coloring h1 a bit off black, removing bold, and shadowing
|
||||||
|
* a touch.
|
||||||
|
*/
|
||||||
|
h1 {
|
||||||
|
color: #505050;
|
||||||
|
text-shadow: 2px 1px 3px rgba(200, 200, 200, 0.43);
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Using some off white for the background color and
|
||||||
|
* padding the top.
|
||||||
|
*/
|
||||||
|
body
|
||||||
|
{
|
||||||
|
background: whitesmoke;
|
||||||
|
padding-top: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make links smaller,
|
||||||
|
*/
|
||||||
|
a
|
||||||
|
{
|
||||||
|
text-shadow: 2px 1px 3px rgba(200, 200, 200, 0.43);
|
||||||
|
padding-bottom: 5px;
|
||||||
|
padding-top: 10px;
|
||||||
|
font-size: 80%;
|
||||||
|
color: #6464ff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre
|
||||||
|
{
|
||||||
|
margin-top: 0px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upper box that contains the title Authorization Server, the UserName, and Password fields
|
||||||
|
*/
|
||||||
|
.upper-box {
|
||||||
|
|
||||||
|
width: 350px;
|
||||||
|
|
||||||
|
border-top: 1px solid;
|
||||||
|
border-left: 1px solid;
|
||||||
|
border-right: 1px solid;
|
||||||
|
|
||||||
|
border-color: lightgrey;
|
||||||
|
border-top-left-radius: 3px;
|
||||||
|
border-top-right-radius: 3px;
|
||||||
|
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-bottom: 35px;
|
||||||
|
|
||||||
|
box-shadow: 1px 1px 5px #e7e7e7;
|
||||||
|
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gradient calculated from gradient calculator of
|
||||||
|
* http://gradients.glrzad.com/
|
||||||
|
*/
|
||||||
|
background-image: linear-gradient(bottom, rgb(249,250,252) 21%, rgb(245,247,250) 67%, rgb(247,249,255) 94%);
|
||||||
|
background-image: -o-linear-gradient(bottom, rgb(249,250,252) 21%, rgb(245,247,250) 67%, rgb(247,249,255) 94%);
|
||||||
|
background-image: -moz-linear-gradient(bottom, rgb(249,250,252) 21%, rgb(245,247,250) 67%, rgb(247,249,255) 94%);
|
||||||
|
background-image: -webkit-linear-gradient(bottom, rgb(249,250,252) 21%, rgb(245,247,250) 67%, rgb(247,249,255) 94%);
|
||||||
|
background-image: -ms-linear-gradient(bottom, rgb(249,250,252) 21%, rgb(245,247,250) 67%, rgb(247,249,255) 94%);
|
||||||
|
|
||||||
|
background-image: -webkit-gradient(
|
||||||
|
linear,
|
||||||
|
left bottom,
|
||||||
|
left top,
|
||||||
|
color-stop(0.21, rgb(249,250,252)),
|
||||||
|
color-stop(0.67, rgb(245,247,250)),
|
||||||
|
color-stop(0.94, rgb(247,249,255))
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bottom box that contains the "Sign in" button
|
||||||
|
*/
|
||||||
|
.bottom-box {
|
||||||
|
border:1px solid;
|
||||||
|
border-color: lightgrey;
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
|
||||||
|
width: 350px;
|
||||||
|
padding-top: 15px;
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
box-shadow: 1px 3px 1px #e7e7e7;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gradient calculated from gradient calculator of
|
||||||
|
* http://gradients.glrzad.com/
|
||||||
|
*/
|
||||||
|
background-image: linear-gradient(bottom, rgb(242,245,250) 21%, rgb(242,245,250) 67%, rgb(242,245,255) 94%);
|
||||||
|
background-image: -o-linear-gradient(bottom, rgb(242,245,250) 21%, rgb(242,245,250) 67%, rgb(242,245,255) 94%);
|
||||||
|
background-image: -moz-linear-gradient(bottom, rgb(242,245,250) 21%, rgb(242,245,250) 67%, rgb(242,245,255) 94%);
|
||||||
|
background-image: -webkit-linear-gradient(bottom, rgb(242,245,250) 21%, rgb(242,245,250) 67%, rgb(242,245,255) 94%);
|
||||||
|
background-image: -ms-linear-gradient(bottom, rgb(242,245,250) 21%, rgb(242,245,250) 67%, rgb(242,245,255) 94%);
|
||||||
|
|
||||||
|
background-image: -webkit-gradient(
|
||||||
|
linear,
|
||||||
|
left bottom,
|
||||||
|
left top,
|
||||||
|
color-stop(0.21, rgb(242,245,250)),
|
||||||
|
color-stop(0.67, rgb(242,245,250)),
|
||||||
|
color-stop(0.94, rgb(242,245,255))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Okay, you caught me. It's a hack to make this look centered.
|
||||||
|
*
|
||||||
|
* TODO Fix this, can't figure out how to get this to center correctly.
|
||||||
|
* It's currently anchored to the fieldset and that's causing issues.
|
||||||
|
*/
|
||||||
|
.title-padding {
|
||||||
|
padding-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The username and password labels
|
||||||
|
*/
|
||||||
|
.labels {
|
||||||
|
color: #505050;
|
||||||
|
text-shadow: 2px 1px 3px rgba(200, 200, 200, 0.43);
|
||||||
|
padding-bottom: 5px;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input fields so I can make it slightly larger than the default,
|
||||||
|
* and I can also pad anything trying to touch it on the right.
|
||||||
|
*/
|
||||||
|
.input-fields {
|
||||||
|
padding-right: 20px;
|
||||||
|
font-size: 130%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This makes all the placeholder text italic. Nice trick I
|
||||||
|
* picked up from stack overflow:
|
||||||
|
* http://stackoverflow.com/questions/16291925/how-to-make-value-text-in-form-be-italic
|
||||||
|
*/
|
||||||
|
::-webkit-input-placeholder { font-style: italic; }
|
||||||
|
::-moz-placeholder { font-style: italic; }
|
||||||
|
:-ms-input-placeholder { font-style: italic; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Very specific to the sign on button.
|
||||||
|
*/
|
||||||
|
.sign-in-button {
|
||||||
|
padding-right: 20px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Very specific to the "from website" link
|
||||||
|
*/
|
||||||
|
.from-text {
|
||||||
|
padding-top: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
8
workflow/public_html/assets/css/style.css
Normal file
8
workflow/public_html/assets/css/style.css
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
body {
|
||||||
|
padding: 50px;
|
||||||
|
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #00B7FF;
|
||||||
|
}
|
||||||
238
workflow/public_html/assets/css/test-modules.css
Normal file
238
workflow/public_html/assets/css/test-modules.css
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
body {
|
||||||
|
color: #777;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-img-responsive {
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add transition to containers so they can push in and out.
|
||||||
|
*/
|
||||||
|
#layout,
|
||||||
|
#menu,
|
||||||
|
.menu-link {
|
||||||
|
-webkit-transition: all 0.2s ease-out;
|
||||||
|
-moz-transition: all 0.2s ease-out;
|
||||||
|
-ms-transition: all 0.2s ease-out;
|
||||||
|
-o-transition: all 0.2s ease-out;
|
||||||
|
transition: all 0.2s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is the parent `<div>` that contains the menu and the content area.
|
||||||
|
*/
|
||||||
|
#layout {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
#layout.active {
|
||||||
|
position: relative;
|
||||||
|
left: 150px;
|
||||||
|
}
|
||||||
|
#layout.active #menu {
|
||||||
|
left: 150px;
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layout.active .menu-link {
|
||||||
|
left: 150px;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
The content `<div>` is where all your content goes.
|
||||||
|
*/
|
||||||
|
.content {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 2em;
|
||||||
|
max-width: 800px;
|
||||||
|
margin-bottom: 50px;
|
||||||
|
line-height: 1.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
margin: 0;
|
||||||
|
color: #333;
|
||||||
|
text-align: center;
|
||||||
|
padding: 2.5em 2em 0;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
}
|
||||||
|
.header h1 {
|
||||||
|
margin: 0.2em 0;
|
||||||
|
font-size: 3em;
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
.header h2 {
|
||||||
|
font-weight: 300;
|
||||||
|
color: #ccc;
|
||||||
|
padding: 0;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-subhead {
|
||||||
|
margin: 50px 0 20px 0;
|
||||||
|
font-weight: 300;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
The `#menu` `<div>` is the parent `<div>` that contains the `.pure-menu` that
|
||||||
|
appears on the left side of the page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#menu {
|
||||||
|
margin-left: -150px; /* "#menu" width */
|
||||||
|
width: 150px;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 1000; /* so the menu or its navicon stays above all content */
|
||||||
|
background: #191818;
|
||||||
|
overflow-y: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
All anchors inside the menu should be styled like this.
|
||||||
|
*/
|
||||||
|
#menu a {
|
||||||
|
color: #999;
|
||||||
|
border: none;
|
||||||
|
padding: 0.6em 0 0.6em 0.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove all background/borders, since we are applying them to #menu.
|
||||||
|
*/
|
||||||
|
#menu .pure-menu,
|
||||||
|
#menu .pure-menu ul {
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add that light border to separate items into groups.
|
||||||
|
*/
|
||||||
|
#menu .pure-menu ul,
|
||||||
|
#menu .pure-menu .menu-item-divided {
|
||||||
|
border-top: 1px solid #333;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Change color of the anchor links on hover/focus.
|
||||||
|
*/
|
||||||
|
#menu .pure-menu li a:hover,
|
||||||
|
#menu .pure-menu li a:focus {
|
||||||
|
background: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This styles the selected menu item `<li>`.
|
||||||
|
*/
|
||||||
|
#menu .pure-menu-selected,
|
||||||
|
#menu .pure-menu-heading {
|
||||||
|
background: #1f8dd6;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
This styles a link within a selected menu item `<li>`.
|
||||||
|
*/
|
||||||
|
#menu .pure-menu-selected a {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This styles the menu heading.
|
||||||
|
*/
|
||||||
|
#menu .pure-menu-heading {
|
||||||
|
font-size: 110%;
|
||||||
|
color: #fff;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- Dynamic Button For Responsive Menu -------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
The button to open/close the Menu is custom-made and not part of Pure. Here's
|
||||||
|
how it works:
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
`.menu-link` represents the responsive menu toggle that shows/hides on
|
||||||
|
small screens.
|
||||||
|
*/
|
||||||
|
.menu-link {
|
||||||
|
position: fixed;
|
||||||
|
display: block; /* show this only on small screens */
|
||||||
|
top: 0;
|
||||||
|
left: 0; /* "#menu width" */
|
||||||
|
background: #000;
|
||||||
|
background: rgba(0,0,0,0.7);
|
||||||
|
font-size: 10px; /* change this value to increase/decrease button size */
|
||||||
|
z-index: 10;
|
||||||
|
width: 2em;
|
||||||
|
height: auto;
|
||||||
|
padding: 2.1em 1.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-link:hover,
|
||||||
|
.menu-link:focus {
|
||||||
|
background: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-link span {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-link span,
|
||||||
|
.menu-link span:before,
|
||||||
|
.menu-link span:after {
|
||||||
|
background-color: #fff;
|
||||||
|
width: 100%;
|
||||||
|
height: 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-link span:before,
|
||||||
|
.menu-link span:after {
|
||||||
|
position: absolute;
|
||||||
|
margin-top: -0.6em;
|
||||||
|
content: " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-link span:after {
|
||||||
|
margin-top: 0.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -- Responsive Styles (Media Queries) ------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
Hides the menu at `48em`, but modify this based on your app's needs.
|
||||||
|
*/
|
||||||
|
@media (min-width: 48em) {
|
||||||
|
|
||||||
|
.header,
|
||||||
|
.content {
|
||||||
|
padding-left: 2em;
|
||||||
|
padding-right: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layout {
|
||||||
|
padding-left: 150px; /* left col width "#menu" */
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
#menu {
|
||||||
|
left: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-link {
|
||||||
|
position: fixed;
|
||||||
|
left: 150px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#layout.active .menu-link {
|
||||||
|
left: 150px;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user