Add API Platform Framework with Symfony/Flex

This implements the basic structure that will be used for the API and core application.
This commit is contained in:
Dillon-Brown 2019-12-30 11:36:29 +00:00
parent bc0c674603
commit 587a79613e
115 changed files with 5489 additions and 6682 deletions

38
.env.dist Normal file
View file

@ -0,0 +1,38 @@
# In all environments, the following files are loaded if they exist,
# the latter taking precedence over the former:
#
# * .env.dist contains default values for the environment variables needed by the app
# * .env.local uncommitted file with local overrides
# * .env.$APP_ENV committed environment-specific defaults
# * .env.$APP_ENV.local uncommitted environment-specific overrides
#
# Real environment variables win over .env files.
#
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
#
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
###> symfony/framework-bundle ###
APP_ENV=dev
APP_SECRET=8d05fae29eaeeda1edf6008093f395b4
#TRUSTED_PROXIES=127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
#TRUSTED_HOSTS='^localhost|example\.com$'
###< symfony/framework-bundle ###
###> nelmio/cors-bundle ###
CORS_ALLOW_ORIGIN=^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$
###< nelmio/cors-bundle ###
###> doctrine/doctrine-bundle ###
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db"
# For a PostgreSQL database, use: "postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=11&charset=utf8"
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=5.7
###< doctrine/doctrine-bundle ###
###> lexik/jwt-authentication-bundle ###
JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem
JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem
JWT_PASSPHRASE=30e1f97a4a670a03fb98ecab5c3e4265
###< lexik/jwt-authentication-bundle ###

4
.env.test.dist Normal file
View file

@ -0,0 +1,4 @@
# define your env variables for the test environment here
KERNEL_CLASS='SuiteCRM\Core\Base\Kernel'
APP_SECRET='$ecretf0rt3st'
SYMFONY_DEPRECATIONS_HELPER=999999

11
.gitignore vendored
View file

@ -1,5 +1,16 @@
## SuiteCRM 8 ## ## SuiteCRM 8 ##
###> symfony/framework-bundle ###
/.env
/.env.local
/.env.local.php
/.env.*.local
/config/secrets/prod/prod.decrypt.private.php
/public/bundles/
/var/
/vendor/
###< symfony/framework-bundle ###
build/ build/
config/ config/
!config/.gitkeep !config/.gitkeep

66
.htaccess Normal file
View file

@ -0,0 +1,66 @@
# Use the front controller as index file. It serves as a fallback solution when
# every other rewrite/redirect fails (e.g. in an aliased environment without
# mod_rewrite). Additionally, this reduces the matching process for the
# start page (path "/") because otherwise Apache will apply the rewriting rules
# to each configured DirectoryIndex file (e.g. index.php, index.html, index.pl).
DirectoryIndex index.php
# By default, Apache does not evaluate symbolic links if you did not enable this
# feature in your server configuration. Uncomment the following line if you
# install assets as symlinks or if you experience problems related to symlinks
# when compiling LESS/Sass/CoffeScript assets.
# Options FollowSymlinks
# Disabling MultiViews prevents unwanted negotiation, e.g. "/index" should not resolve
# to the front controller "/index.php" but be rewritten to "/index.php/index".
<IfModule mod_negotiation.c>
Options -MultiViews
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine On
# Determine the RewriteBase automatically and set it as environment variable.
# If you are using Apache aliases to do mass virtual hosting or installed the
# project in a subdirectory, the base path will be prepended to allow proper
# resolution of the index.php file and to redirect to the correct URI. It will
# work in environments without path prefix as well, providing a safe, one-size
# fits all solution. But as you do not need it in this case, you can comment
# the following 2 lines to eliminate the overhead.
RewriteCond %{REQUEST_URI}::$0 ^(/.+)/(.*)::\2$
RewriteRule .* - [E=BASE:%1]
# Sets the HTTP_AUTHORIZATION header removed by Apache
RewriteCond %{HTTP:Authorization} .+
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0]
# Redirect to URI without front controller to prevent duplicate content
# (with and without `/index.php`). Only do this redirect on the initial
# rewrite by Apache and not on subsequent cycles. Otherwise we would get an
# endless redirect loop (request -> rewrite to front controller ->
# redirect -> request -> ...).
# So in case you get a "too many redirects" error or you always get redirected
# to the start page because your Apache does not expose the REDIRECT_STATUS
# environment variable, you have 2 choices:
# - disable this feature by commenting the following 2 lines or
# - use Apache >= 2.3.9 and replace all L flags by END flags and remove the
# following RewriteCond (best solution)
RewriteCond %{ENV:REDIRECT_STATUS} =""
RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=301,L]
# If the requested filename exists, simply serve it.
# We only want to let Apache serve files and not directories.
# Rewrite all other queries to the front controller.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ %{ENV:BASE}/index.php [L]
</IfModule>
<IfModule !mod_rewrite.c>
<IfModule mod_alias.c>
# When mod_rewrite is not available, we instruct a temporary redirect of
# the start page to the front controller explicitly so that the website
# and the generated links can still be used.
RedirectMatch 307 ^/$ /index.php/
# RedirectTemp cannot be used instead
</IfModule>
</IfModule>

View file

@ -1,25 +1,10 @@
#!/usr/bin/env php #!/usr/bin/env php
<?php <?php
define('BASE_PATH', dirname(__DIR__) . '/'); use SuiteCRM\Core\src\Kernel;
define('APP_PATH', dirname(__DIR__) . '/core/modules'); use Symfony\Bundle\FrameworkBundle\Console\Application;
define('LEGACY_PATH', __DIR__ . '/legacy/'); use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\ErrorHandler\Debug;
require BASE_PATH . 'vendor/autoload.php';
use Doctrine\Common\Cache\ArrayCache;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\DBALException;
use Doctrine\ORM\Events;
use Doctrine\ORM\ORMException;
use SuiteCRM\Core\Base\Config\Manager as ConfigManager;
use SuiteCRM\Core\Base\Helper\File\File;
use SuiteCRM\Core\Base\Cli\CommandMapper;
use Symfony\Component\Console\Application;
use Doctrine\ORM\Tools\Console\ConsoleRunner;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver;
if (count($argv) === 1 && $argv[0] === 'bin/console') { if (count($argv) === 1 && $argv[0] === 'bin/console') {
echo echo
@ -37,77 +22,42 @@ if (count($argv) === 1 && $argv[0] === 'bin/console') {
"; ";
} }
$application = new Application('Version 1.0'); if (false === in_array(PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) {
echo 'Warning: The console should be invoked via the CLI version of PHP, not the ' . PHP_SAPI . ' SAPI' . PHP_EOL;
}
$configManager = new ConfigManager(); set_time_limit(0);
require dirname(__DIR__) . '/vendor/autoload.php';
if (!class_exists(Application::class)) {
throw new RuntimeException('You need to add "symfony/framework-bundle" as a Composer dependency.');
}
$input = new ArgvInput();
if (null !== $env = $input->getParameterOption(['--env', '-e'], null, true)) {
putenv('APP_ENV=' . $_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $env);
}
if ($input->hasParameterOption('--no-debug', true)) {
putenv('APP_DEBUG=' . $_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0');
}
require dirname(__DIR__) . '/config/bootstrap.php';
if ($_SERVER['APP_DEBUG']) {
umask(0000);
if (class_exists(Debug::class)) {
/** @noinspection UnusedFunctionResultInspection */
Debug::enable();
}
}
$kernel = new Kernel($_SERVER['APP_ENV'], (bool)$_SERVER['APP_DEBUG']);
$application = new Application($kernel);
try { try {
$appConfig = $configManager->loadFiles(BASE_PATH . 'config/config.yml'); $application->run($input);
} catch (Exception $e) { } catch (Exception $exception) {
trigger_error('CLI failed to load files: ' . $e); echo 'An error occurred while attempting to run the application ' . $exception->getMessage();
}
if ($appConfig->has('storage.mysql')) {
$connectionParams = $appConfig->get('storage.mysql');
$namespaces = $appConfig->get('entity.namespaces');
$driver = new SimplifiedYamlDriver($namespaces);
$isDevMode = false;
if ($appConfig->has('server.environment') && $appConfig->get('server.environment') === 'develop') {
$isDevMode = true;
}
$config = Setup::createYAMLMetadataConfiguration($namespaces, $isDevMode);
$cache = new ArrayCache();
$config->setMetadataCacheImpl($cache);
$config->setQueryCacheImpl($cache);
$config->setMetadataDriverImpl($driver);
// Table Prefix
$evm = new EventManager();
$tablePrefix = new SuiteCRM\Core\Base\Module\Storage\TablePrefix('suite8_');
$evm->addEventListener(Events::loadClassMetadata, $tablePrefix);
try {
$entityManager = EntityManager::create($connectionParams, $config, $evm);
} catch (ORMException $e) {
trigger_error('CLI failed to get create entity manager instance: ' . $e);
}
//-- This I had to add to support the Mysql enum type.
try {
$platform = $entityManager->getConnection()->getDatabasePlatform();
} catch (DBALException $e) {
trigger_error('CLI failed to get DB platform: ' . $e);
}
try {
$platform->registerDoctrineTypeMapping('enum', 'string');
} catch (DBALException $e) {
trigger_error('CLI failed to get register doctrine type mapping: ' . $e);
}
$helperSet = ConsoleRunner::createHelperSet($entityManager);
}
$configPath = [BASE_PATH . 'config/config.yml', BASE_PATH . 'core/base/Config/modules.config.yml'];
$fileHelper = new File();
$commandMapper = new CommandMapper($fileHelper, $configManager, $configPath);
$application->setHelperSet($helperSet);
$application->addCommands($commandMapper->getAllCommands());
ConsoleRunner::addCommands($application);
// Run Console Application
try {
$application->run();
} catch (Exception $e) {
trigger_error('Application run failure: ' . $e);
} }

View file

@ -13,26 +13,47 @@
}, },
"require": { "require": {
"ext-json": "*", "ext-json": "*",
"api-platform/api-pack": "^1.2",
"bshaffer/oauth2-server-httpfoundation-bridge": "^1.4", "bshaffer/oauth2-server-httpfoundation-bridge": "^1.4",
"bshaffer/oauth2-server-php": "^1.11.1", "bshaffer/oauth2-server-php": "^1.11.1",
"composer/installers": "~1.0", "composer/installers": "~1.0",
"doctrine/cache": "^1.8", "doctrine/cache": "^1.8",
"doctrine/dbal": "^2.9", "doctrine/dbal": "^2.9",
"doctrine/orm": "2.6.*", "doctrine/orm": "2.6.*",
"lexik/jwt-authentication-bundle": "^2.6",
"monolog/monolog": "^1.23", "monolog/monolog": "^1.23",
"phpdocumentor/type-resolver": "^0.4.0",
"pimple/pimple": "^3.2",
"psr/log": "^1.1",
"symfony/cache": "^4.4",
"symfony/config": "^4.2", "symfony/config": "^4.2",
"symfony/console": "^4.3", "symfony/console": "^4.4",
"symfony/dependency-injection": "^4.4",
"symfony/dotenv": "^4.4",
"symfony/error-handler": "^4.4",
"symfony/filesystem": "^4.4",
"symfony/finder": "^4.4",
"symfony/flex": "^1.6",
"symfony/framework-bundle": "^4.4",
"symfony/http-foundation": "^4.2", "symfony/http-foundation": "^4.2",
"symfony/http-kernel": "^4.4",
"symfony/monolog-bundle": "^3.5",
"symfony/routing": "4.4.x-dev", "symfony/routing": "4.4.x-dev",
"symfony/yaml": "^4.2" "symfony/yaml": "^4.2",
"thecodingmachine/graphqlite": "^3.1",
"webonyx/graphql-php": "^0.13.8"
}, },
"require-dev": { "require-dev": {
"roave/security-advisories": "dev-master", "dama/doctrine-test-bundle": "^5.0",
"phpunit/phpunit": "^7.3",
"phpmetrics/phpmetrics": "^2.4.1",
"phploc/phploc": "^4.0.1",
"doctrine/doctrine-fixtures-bundle": "~3.2", "doctrine/doctrine-fixtures-bundle": "~3.2",
"dama/doctrine-test-bundle": "^5.0" "phploc/phploc": "^4.0.1",
"phpmetrics/phpmetrics": "^2.4.1",
"phpunit/phpunit": "^7.3",
"roave/security-advisories": "dev-master",
"symfony/maker-bundle": "^1.14"
},
"conflict": {
"symfony/symfony": "*"
}, },
"license": "GPL-3.0", "license": "GPL-3.0",
"authors": [ "authors": [
@ -44,9 +65,19 @@
"psr-4": { "psr-4": {
"SuiteCRM\\Core\\Base\\": "core/base/", "SuiteCRM\\Core\\Base\\": "core/base/",
"SuiteCRM\\Core\\Modules\\": "core/modules/", "SuiteCRM\\Core\\Modules\\": "core/modules/",
"SuiteCRM\\Core\\Legacy\\": "core/legacy/" "SuiteCRM\\Core\\Legacy\\": "core/legacy/",
"App\\Command\\": "core/base/src/Command/"
} }
}, },
"minimum-stability": "dev", "minimum-stability": "dev",
"prefer-stable": true "prefer-stable": true,
"extra": {
"src-dir": "core/base/src"
},
"scripts": {
"auto-scripts": {
"cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd"
}
}
} }

5790
composer.lock generated

File diff suppressed because it is too large Load diff

24
config/bootstrap.php Normal file
View file

@ -0,0 +1,24 @@
<?php
use Symfony\Component\Dotenv\Dotenv;
require dirname(__DIR__) . '/vendor/autoload.php';
// Load cached env vars if the .env.local.php file exists
// Run "composer dump-env prod" to create it (requires symfony/flex >=1.2)
if (is_array($env = @include dirname(__DIR__) . '/.env.local.php') && ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env['APP_ENV']) === $env['APP_ENV']) {
foreach ($env as $k => $v) {
$_ENV[$k] = $_ENV[$k] ?? (isset($_SERVER[$k]) && 0 !== strpos($k, 'HTTP_') ? $_SERVER[$k] : $v);
}
} elseif (!class_exists(Dotenv::class)) {
throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.');
} else {
// load all the .env files
(new Dotenv(false))->loadEnv(dirname(__DIR__) . '/.env');
}
$_SERVER += $_ENV;
$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev';
$_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV'];
$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int)$_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'],
FILTER_VALIDATE_BOOLEAN) ? '1' : '0';

12
config/bundles.php Normal file
View file

@ -0,0 +1,12 @@
<?php
return [
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
ApiPlatform\Core\Bridge\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true],
DAMA\DoctrineTestBundle\DAMADoctrineTestBundle::class => ['test' => true],
Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true],
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
];

View file

@ -0,0 +1,39 @@
api_platform:
graphql:
graphiql:
enabled: false
graphql_playground:
enabled: false
mapping:
paths: ['%kernel.project_dir%/core']
patch_formats:
json: ['application/merge-patch+json']
graphql: ['application/graphql']
swagger:
versions: [3]
oauth:
# To enable or disable oauth.
enabled: true
# The oauth client id.
clientId: 'scrmfe'
# The oauth client secret.
clientSecret: 'scrmfe'
# The oauth type.
type: 'oauth2'
# The oauth flow grant type.
flow: 'password'
# The oauth token url.
tokenUrl: '/oauth/v2/token'
# The oauth authentication url.
authorizationUrl: '/oauth/v2/auth'
# The oauth scopes.
scopes: []
enable_swagger_ui: false

View file

@ -0,0 +1,19 @@
framework:
cache:
# Unique name of your app: used to compute stable namespaces for cache keys.
#prefix_seed: your_vendor_name/app_name
# The "app" cache stores to the filesystem by default.
# The data in this cache should persist between deploys.
# Other options include:
# Redis
#app: cache.adapter.redis
#default_redis_provider: redis://localhost
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
#app: cache.adapter.apcu
# Namespaced pools use the above "app" backend by default
#pools:
#my.dedicated.cache: null

View file

@ -0,0 +1,19 @@
monolog:
handlers:
main:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
channels: ["!event"]
# uncomment to get logging in your browser
# you may have to allow bigger header sizes in your Web server configuration
#firephp:
# type: firephp
# level: info
#chromephp:
# type: chromephp
# level: info
console:
type: console
process_psr_3_messages: false
channels: ["!event", "!doctrine", "!console"]

View file

@ -0,0 +1,18 @@
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%'
# IMPORTANT: You MUST configure your server version,
# either here or in the DATABASE_URL env var (see .env file)
#server_version: '5.7'
orm:
auto_generate_proxy_classes: true
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
auto_mapping: true
mappings:
App:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/core/modules'
prefix: 'SuiteCRM\Core\Modules\'
alias: App

View file

@ -0,0 +1,16 @@
framework:
secret: '%env(APP_SECRET)%'
#csrf_protection: true
#http_method_override: true
# Enables session support. Note that the session will ONLY be started if you read or write from it.
# Remove or comment this section to explicitly disable session support.
session:
handler_id: null
cookie_secure: auto
cookie_samesite: lax
#esi: true
#fragments: true
php_errors:
log: true

View file

@ -0,0 +1,20 @@
doctrine:
orm:
auto_generate_proxy_classes: false
metadata_cache_driver:
type: pool
pool: doctrine.system_cache_pool
query_cache_driver:
type: pool
pool: doctrine.system_cache_pool
result_cache_driver:
type: pool
pool: doctrine.result_cache_pool
framework:
cache:
pools:
doctrine.result_cache_pool:
adapter: cache.app
doctrine.system_cache_pool:
adapter: cache.system

View file

@ -0,0 +1,23 @@
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: nested
excluded_http_codes: [404, 405]
nested:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
console:
type: console
process_psr_3_messages: false
channels: ["!event", "!doctrine"]
deprecation:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.deprecations.log"
deprecation_filter:
type: filter
handler: deprecation
max_level: info
channels: ["php"]

View file

@ -0,0 +1,3 @@
framework:
router:
strict_requirements: null

View file

@ -0,0 +1,3 @@
framework:
router:
utf8: true

View file

@ -0,0 +1,22 @@
security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
in_memory: { memory: null }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: lazy
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#firewalls-authentication
# https://symfony.com/doc/current/security/impersonating_user.html
# switch_user: true
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
# - { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }

View file

@ -0,0 +1,4 @@
dama_doctrine_test:
enable_static_connection: true
enable_static_meta_data_cache: true
enable_static_query_cache: true

View file

@ -0,0 +1,4 @@
framework:
test: true
session:
storage_id: session.storage.mock_file

View file

@ -0,0 +1,7 @@
monolog:
handlers:
main:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
channels: ["!event"]

View file

@ -0,0 +1,2 @@
twig:
strict_variables: true

View file

@ -0,0 +1,3 @@
framework:
validation:
not_compromised_password: false

View file

@ -0,0 +1,2 @@
twig:
default_path: '%kernel.project_dir%/templates'

View file

@ -0,0 +1,8 @@
framework:
validation:
email_validation_mode: html5
# Enables validator auto-mapping support.
# For instance, basic validation constraints will be inferred from Doctrine's metadata.
#auto_mapping:
# App\Entity\: []

View file

@ -0,0 +1,4 @@
api_platform:
resource: .
type: api_platform
prefix: /api

View file

@ -0,0 +1,3 @@
_errors:
resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
prefix: /_error

28
config/services.yaml Normal file
View file

@ -0,0 +1,28 @@
framework:
secret: "%secret%"
parameters:
secret: ThisTokenIsNotSoSecretChangeIt
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
bind:
$projectDir: '%kernel.project_dir%'
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../core/src/*'
exclude: '../core/src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
SuiteCRM\Core\Modules\:
resource: '../core/modules/'
tags: ['controller.service_arguments']
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones

View file

@ -1,106 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Cli;
use SuiteCRM\Core\Base\Helper\File\File;
use SuiteCRM\Core\Base\Config\Manager as ConfigManager;
use SuiteCRM\Core\Base\Module\Manager as ModuleManager;
/**
* Class CommandMapper
* @package SuiteCRM\Core\Base\Cli
*/
class CommandMapper
{
/**
*
* @var File
*/
protected $fileHelper;
/**
*
* @var array
*/
protected $configParameters;
/**
*
* @var array
*/
protected $enabledModules;
/**
* CommandMapper constructor.
* @param File $file
* @param ConfigManager $config
* @param $config_path
*/
public function __construct(File $file, ConfigManager $config, $config_path)
{
$this->fileHelper = $file;
try {
$this->configParameters = $config->loadFiles($config_path);
} catch (\Exception $e) {
trigger_error('Config failed to load files: ' . $e);
}
$this->enabledModules = $this->configParameters->get('modules.enabled');
}
public function getAllModules(): void
{
$modules = (new ModuleManager($this->configParameters, $this->fileHelper))->getAllModules();
$this->enabledModules = $modules;
}
/**
* @return array
*/
public function getAllCommands(): array
{
$commandClasses = [];
$filePaths = [];
if (empty($this->enabledModules)) {
$this->getAllModules();
}
if (!empty($this->enabledModules)) {
foreach ($this->enabledModules as $module) {
$filePaths[] = APP_PATH . '/' . $module . '/Cli';
}
}
$files = $this->fileHelper->findFiles($filePaths, '/Command.php$/');
if (!empty($files)) {
foreach ($files as $file) {
$parts = explode('/', $file);
$key = array_search('modules', $parts, true);
$parts = array_splice($parts, ($key + 1), count($parts));
$filename = end($parts);
$classname = rtrim($filename, '.php');
$keys = array_keys($parts);
$key = end($keys);
$parts[$key] = $classname;
$commandClass = 'SuiteCRM\\Core\\Modules\\' . implode('\\', $parts);
$commandClasses[] = new $commandClass($this->configParameters);
}
}
return $commandClasses;
}
}

View file

@ -1,19 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Cli;
use Symfony\Component\Console\Command\Command;
/**
* Class SuiteCommand
* @package SuiteCRM\Core\Base\Cli
*/
class SuiteCommand extends Command
{
protected $config;
public function __construct()
{
parent::__construct();
}
}

View file

@ -1,42 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Config\Loader;
use Exception;
use Symfony\Component\Config\Loader\FileLoader;
use Symfony\Component\Yaml\Yaml;
/**
* Class YamlLoader
* @package SuiteCRM\Core\Base\Config\Loader
*/
class YamlLoader extends FileLoader
{
/**
*
* @param mixed $resource The resource
* @param string|null $type The resource type or null if unknown
* @return mixed The YAML converted to a PHP value
* @throws Exception
*/
public function load($resource, $type = null)
{
$contents = file_get_contents($resource);
return Yaml::parse($contents);
}
/**
* @param mixed $resource
* @param null $type
* @return bool
*/
public function supports($resource, $type = null): bool
{
return is_string($resource) && 'yml' === pathinfo(
$resource,
PATHINFO_EXTENSION
);
}
}

View file

@ -1,65 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Config;
use SuiteCRM\Core\Base\Config\Loader\YamlLoader;
use SuiteCRM\Core\Base\Helper\Data\CollectionInterface;
use SuiteCRM\Core\Base\Helper\File\FileMapperInterface;
use SuiteCRM\Core\Base\Config\ParameterCollection;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\Loader\DelegatingLoader;
use Symfony\Component\Config\FileLocator;
/**
* Class Manager
* @package SuiteCRM\Core\Base\Config
*/
class Manager implements FileMapperInterface
{
/**
* Load the current configuration files
*
* @param bool $config_paths The config paths to load resources
* @return CollectionInterface
* @throws \Exception
*/
public function loadFiles($config_paths = false): CollectionInterface
{
if ($config_paths === false) {
throw new \RuntimeException('Config paths need to be set up correctly');
}
// Get array from config paths
$configPaths = (array)$config_paths;
$fileLocator = new FileLocator($configPaths);
// Check paths exists
foreach ($configPaths as $path) {
$fileLocator->locate($path);
}
$loaderResolver = new LoaderResolver([new YamlLoader($fileLocator)]);
$delegatingLoader = new DelegatingLoader($loaderResolver);
// All config parameters
$allParameters = [];
if ($configPaths !== false) {
foreach ($configPaths as $path) {
// Load the parameters from the path resource
$parameters = $delegatingLoader->load($path);
// Merge parameters together
if (!empty($parameters)) {
$allParameters = array_merge($allParameters, $parameters);
}
}
}
return new ParameterCollection($allParameters);
}
}

View file

@ -1,13 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Config;
use SuiteCRM\Core\Base\Helper\Data\Collection;
/**
* Class ParameterCollection
* @package SuiteCRM\Core\Base\Config
*/
class ParameterCollection extends Collection
{
}

View file

@ -1,4 +0,0 @@
modules:
enabled:
- Administration
- Users

View file

@ -1,2 +0,0 @@
services:
users.authentication: 'SuiteCRM\Core\Legacy\AuthenticationService'

View file

@ -1,127 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Helper\Data;
/**
* Class Collection
* @package SuiteCRM\Core\Base\Helper\Data
*/
class Collection implements CollectionInterface
{
/**
*
* @var array
*/
protected $data = [];
/**
* Load the collection
*
* @param array $data Array of data to collect
*/
public function __construct($data = [])
{
return $this->load($data);
}
/**
* Recursive function to collect the collection data
*
* @param array $data The collection data
* @param string $parent_key The parent keys attached to the child array
* @return bool
*/
public function load($data, $parent_key = ''): bool
{
if (empty($data)) {
return false;
}
$parentKey = ($parent_key !== '') ? $parent_key . '.' : '';
foreach ($data as $key => $val) {
if (is_array($val)) {
$this->load($data[$key], $parentKey . $key);
}
$this->data[$parentKey . $key] = $val;
}
return true;
}
/**
* Get all config variable
*
* @return array
*/
public function getAll(): array
{
return $this->data;
}
/**
* Get collection data
*
* @param string $key
* @return bool|mixed
*/
public function get($key)
{
return ($this->has($key)) ? $this->data[$key] : false;
}
/**
* Set collection data
*
* @param string $key Name of parameter to set
* @param mixed $value Value to set
*/
public function set($key, $value): void
{
$this->data[$key] = $value;
}
/**
* Find out if parameter exists
*
* @param string $key Name to find out
* @return bool
*/
public function has($key): bool
{
return isset($this->data[$key]);
}
/**
* Count collection entry for key
*
* @param string|null $key The config key you want to count
* @return int
*/
public function count($key = null): int
{
return ($key === null) ? count($this->data) : count($this->data[$key]);
}
/**
* Check if the collection key is empty
*
* @param string $key
* @return bool true if empty - false - if not
*/
public function isEmpty($key): bool
{
$has = $this->has($key);
if ($has) {
$count = $this->count($key);
if ($count > 0) {
return false;
}
}
return true;
}
}

View file

@ -1,50 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Helper\Data;
/**
* Interface CollectionInterface
* @package SuiteCRM\Core\Base\Helper\Data
*/
interface CollectionInterface
{
/**
* @param $data
* @param string $parent_key
* @return mixed
*/
public function load($data, $parent_key = '');
public function getAll();
/**
* @param $key
* @return mixed
*/
public function get($key);
/**
* @param $key
* @param $value
* @return mixed
*/
public function set($key, $value);
/**
* @param $key
* @return mixed
*/
public function has($key);
/**
* @param $key
* @return mixed
*/
public function count($key);
/**
* @param $key
* @return mixed
*/
public function isEmpty($key);
}

View file

@ -1,172 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Helper\File;
use \RecursiveDirectoryIterator;
use \FilesystemIterator;
use \RecursiveIteratorIterator;
/**
* Class File
* @package SuiteCRM\Core\Base\Helper\File
*/
class File
{
/**
* Get all directories in a path
*
* @param $paths array|string of paths
* @return array All directories in paths
*/
public function findDirectories($paths): array
{
$directories = [];
// Cast to array if string
$paths = (array)$paths;
foreach ($paths as $path) {
foreach (new \DirectoryIterator($path) as $fileInfo) {
if ($fileInfo->isDot()) {
continue;
}
if ($fileInfo->isDir()) {
$directories[] = $fileInfo->getFilename();
}
}
}
asort($directories);
return array_values($directories);
}
/**
* Make directory
*
* @param string $path
* @param int $permissions octal
* @return bool
*/
public function makeDir($path, $permissions = 0755): bool
{
return is_dir($path) || mkdir($path, $permissions, true) || is_dir($path);
}
/**
* Delete a directory and all files
*
* @param string $dir The directory path you want to delete
* @param array $files_to_leave
* @return bool True - successfully deleted False - issue with deletion
*/
public function deleteDirectory(string $dir, array $files_to_leave = []): bool
{
$di = new RecursiveDirectoryIterator($dir, FilesystemIterator::SKIP_DOTS);
$ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::CHILD_FIRST);
if (empty($files_to_leave)) {
foreach ($ri as $file) {
$file->isDir() ? rmdir($file) : unlink($file);
}
} else {
foreach ($ri as $file) {
if (strpos($file->getPathName(), $files_to_leave[0]) === false) {
$file->isDir() ? rmdir($file) : unlink($file);
}
}
}
return (!$this->isDirectoryEmpty($dir)) ?: rmdir($dir);
}
/**
* Check to see if directory is empty
*
* @param string $dir
* @return bool
*/
public function isDirectoryEmpty($dir): bool
{
if (!is_readable($dir)) {
return null;
}
return (count(scandir($dir)) == 2);
}
/**
* File files
*
* @param string|array $directories The directory to look in
* @param string $search The pattern to find the files
* @return array
*/
public function findFiles($directories, $search): array
{
$foundFiles = [];
// Convert to array if string given
if (is_string($directories)) {
$directories = [$directories];
}
foreach ($directories as $directory) {
$directory = realpath($directory);
if (!is_dir($directory)) {
continue;
}
$objDirectory = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
$iterator = new RecursiveIteratorIterator($objDirectory);
$files = new \RegexIterator($iterator, $search, \RecursiveRegexIterator::GET_MATCH);
if ($files !== null) {
foreach ($files as $key => $value) {
$foundFiles[] = $key;
}
}
}
return $foundFiles;
}
/**
* Copy files recursively
* @param $src
* @param $dst
*/
public function recurseCopy($src, $dst): void
{
$dir = \opendir($src);
if (!is_dir($dst)) {
try {
if (!mkdir($dst, 0755, true) && !is_dir($dst)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $dst));
}
} catch (\Exception $e) {
throw new \RuntimeException($e->getMessage());
}
}
chmod($dst, 0755);
while (false !== ($file = \readdir($dir))) {
if (($file !== '.') && ($file !== '..')) {
if (\is_dir($src . '/' . $file)) {
$this->recurseCopy($src . '/' . $file, $dst . '/' . $file);
} else {
\copy($src . '/' . $file, $dst . '/' . $file);
}
}
}
\closedir($dir);
}
}

View file

@ -1,18 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Helper\File;
use SuiteCRM\Core\Base\Helper\Data\CollectionInterface;
/**
* Interface FileMapperInterface
* @package SuiteCRM\Core\Base\Helper\File
*/
interface FileMapperInterface
{
/**
* @param $paths
* @return CollectionInterface
*/
public function loadFiles($paths): CollectionInterface;
}

View file

@ -1,42 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Http;
use Symfony\Component\HttpFoundation\Request as HttpFoundationRequest;
/**
* Class Request
* @package SuiteCRM\Core\Base\Http
*/
class Request extends HttpFoundationRequest
{
/**
* Request constructor.
* @param array $query
* @param array $request
* @param array $attributes
* @param array $cookies
* @param array $files
* @param array $server
* @param null $content
*/
public function __construct(
array $query = [],
array $request = [],
array $attributes = [],
array $cookies = [],
array $files = [],
array $server = [],
$content = null
) {
parent::__construct(
$query,
$request,
$attributes,
$cookies,
$files,
$server,
$content
);
}
}

View file

@ -1,14 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Http;
use Symfony\Component\HttpFoundation\Response as HttpFoundationResponse;
/**
* Class Response
* @package SuiteCRM\Core\Base\Http
*/
class Response extends HttpFoundationResponse
{
}

View file

@ -1,109 +0,0 @@
<?php
namespace SuiteCRM\Core\Base;
use SuiteCRM\Core\Base\RunnableInterface;
use SuiteCRM\Core\Base\Helper\Data\CollectionInterface;
/**
* Class Instance
* @package SuiteCRM\Core\Base
*/
class Instance implements RunnableInterface
{
/**
*
* @var SuiteCRM\Core\Base\Module\Manager
*/
protected $modules;
/**
*
* @var stdClass
*/
protected $route;
/**
*
* @var SuiteCRM\Core\Base\Config\Handler
*/
protected $config;
/**
*
* @var array
*/
protected $fileHelper;
/**
* Instance constructor.
* @param CollectionInterface $config
* @param $route
* @param $modules
*/
public function __construct(CollectionInterface $config, $route, $modules)
{
$this->modules = $modules;
$this->config = $config;
$this->route = $route;
}
/**
* Run the Application
*
* @return mixed
*/
public function run()
{
return $this;
}
/**
* Get all routes from enabled modules
*
* @return array
*/
public function getAllRoutes(): ?array
{
$allRoutes = [];
foreach ($this->modules as $module) {
$allRoutes = array_merge($allRoutes, $module);
}
return $allRoutes;
}
/**
* Get the route of the instance call
*
* @return mixed
* @throws \Exception
*/
public function getRoute()
{
if ($this->route === null) {
throw new \RuntimeException('Route was not configured');
}
return $this->route;
}
/**
* Get all services
*
* @return array
*/
public function getAllServices(): array
{
$allServices = [];
foreach ($this->modules as $module) {
$allServices = array_merge($allServices, $module);
}
return $allServices;
}
}

View file

@ -1,294 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Module;
use Doctrine\Common\Cache\ArrayCache;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\DBALException;
use Doctrine\ORM\Events;
use Doctrine\ORM\ORMException;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Tools\Setup;
use Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver;
use SuiteCRM\Core\Base\Config\ParameterCollection;
use SuiteCRM\Core\Base\Http\Request;
use SuiteCRM\Core\Base\Http\Response;
use SuiteCRM\Core\Base\Module\Service\ServiceCollection;
use SuiteCRM\Core\Base\Module\Storage\TablePrefix;
use SuiteCRM\Core\Base\Module\View\Handler;
use Exception;
/**
* Class Controller
* @package SuiteCRM\Core\Base\Module
*/
class Controller
{
/**
*
* @var ParameterCollection
*/
protected $config;
/**
*
* @var Request
*/
protected $requestObj;
/**
*
* @var Response
*/
protected $responseObj;
/**
*
* @var Session
*/
protected $session;
/**
*
* @var Handler
*/
protected $view;
/**
*
* @var ServiceCollection
*/
protected $services;
/**
*
* @var LegacyWrapper
*/
protected $legacy;
/**
*
* @var array
*/
protected $templates;
/**
*
* @var array
*/
protected $form;
/**
* Load base controller variables
*
* @param ParameterCollection $config
* @param Request $request
* @param Response $response
* @param Handler $view
* @param Service\ServiceCollection $services
*/
public function __construct(
ParameterCollection $config,
Request $request,
Response $response,
Handler $view,
ServiceCollection $services
) {
$this->config = $config;
$this->requestObj = $request;
$this->responseObj = $response;
$this->view = $view;
$this->services = $services;
if ($this->config->has('storage.mysql.driver')) {
$connectionParams = $this->config->get('storage.mysql');
$namespaces = $this->config->get('entity.namespaces');
$realNamespaces = [];
foreach ($namespaces as $path => $namespace) {
$realPath = realpath($path);
if ($realPath !== false) {
$realNamespaces[$realPath] = $namespace;
}
}
$driver = new SimplifiedYamlDriver($realNamespaces);
$realNamespaces = [];
foreach ($namespaces as $path => $namespace) {
$realPath = realpath($path);
if ($realPath !== false) {
$realNamespaces[$realPath] = $namespace;
}
}
$driver = new SimplifiedYamlDriver($realNamespaces);
$isDevMode = false;
if ($this->config->has('server.environment') && $this->config->get('server.environment') === 'develop') {
$isDevMode = true;
}
$config = Setup::createYAMLMetadataConfiguration(
(array)$namespaces,
$isDevMode
);
$cache = new ArrayCache();
$config->setMetadataCacheImpl($cache);
$config->setQueryCacheImpl($cache);
$config->setMetadataDriverImpl($driver);
// Table Prefix
$evm = new EventManager();
$tablePrefix = new TablePrefix('suite8_');
$evm->addEventListener(Events::loadClassMetadata, $tablePrefix);
try {
$entityManager = EntityManager::create($connectionParams, $config, $evm);
} catch (ORMException $e) {
trigger_error('Failed to get create entity manager instance: ' . $e);
}
//-- This I had to add to support the Mysql enum type.
try {
$platform = $entityManager->getConnection()->getDatabasePlatform();
} catch (DBALException $e) {
trigger_error('Failed to get DB platform: ' . $e);
}
try {
$platform->registerDoctrineTypeMapping('enum', 'string');
} catch (DBALException $e) {
trigger_error('Failed to get register doctrine type mapping: ' . $e);
}
$this->em = $entityManager;
}
}
/**
* Get a storage class
*
* @param $namespace
* @return object
*/
public function getStorage($namespace)
{
[$module, $entityName] = explode('.', $namespace);
return $this->em->getRepository(
'SuiteCRM\Core\Modules\\' . ucfirst($module) . '\Entity\\' . ucfirst($entityName)
);
}
/**
* Get a service class
*
* @param $serviceName
* @return object
* @throws Exception
*/
public function getService($serviceName)
{
if (!$this->services->has($serviceName)) {
throw new \RuntimeException('No Service Found: ' . $serviceName);
}
return $this->services->get($serviceName);
}
/**
* Quick function to allow for $this->render
*
* @param $view
* @param array $params
* @param string $template
* @return string
*/
public function render($view, $params = [], $template = 'default.html.php'): string
{
return $this->view->render($view, $params, $template);
}
/**
* Redirect to URL
*
* @param mixed $url Array or string
* @param mixed $params Params too be sent
* @param int $statusCode
* @todo Get Base URL, Concat the Base URL with Route (Controller, Action), Test Array and String
*
*/
public function redirect($url, $params = [], $statusCode = 303): void
{
$this->session->set('redirectPost', $params);
if (is_array($url)) {
$url = implode('/', $url);
}
$urlHelper = new Url();
header('Location: ' . $urlHelper->baseUrl() . $url, true, $statusCode);
die();
}
/**
* Redirect to URL
*
* @param mixed $url URL to redirect to
* @param int $statusCode Forces the HTTP response code to the specified value. Note that this parameter only has an effect if the header is not empty.
*/
public function redirectToUrl($url, $statusCode = 303): void
{
header('Location: ' . $url, true, $statusCode);
die();
}
/**
* Create a flash message.
*
* @param string $message Flash Message
* @param string $type Type of Message
* @return void
* @todo create one time session var for flash_msg,
*
*/
public function flashMsg($message, $type = 'default'): void
{
$this->session->set('flashMsg', ['message' => $message, 'type' => $type], 1);
}
/**
* @param $template
* @param $params
*/
public function renderTemplate($template, $params): void
{
$response = [
'template' => '
<div id="harbour">
<button (click)="window.alert(\'clicked\')">
Click Me
</button>
</div>
',
'scripts' => [
'https://code.jquery.com/jquery-3.4.1.min.js'
]
];
header('Content-Type: application/json');
echo json_encode($response);
}
}

View file

@ -1,134 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Module;
use SuiteCRM\Core\Base\Helper\File\File;
use SuiteCRM\Core\Base\Helper\Data\CollectionInterface;
/**
* Class Manager
* @package SuiteCRM\Core\Base\Module
*/
class Manager
{
/**
*
* @var CollectionInterface
*/
protected $config;
/**
*
* @var File
*/
protected $fileHelper;
/**
* Object Setup
*
* @param CollectionInterface $config
* @param File $file_helper
*/
public function __construct(CollectionInterface $config, File $file_helper)
{
$this->config = $config;
$this->fileHelper = $file_helper;
}
/**
* Get Module Paths
*
* @return array
*/
public function getModulePaths(): array
{
// Get config module paths if set
if (!$this->config->isEmpty('modules.paths')) {
$modulePaths = [];
$configModulePaths = $this->config->get('modules.paths');
foreach ($configModulePaths as $modulePath) {
$modulePaths[] = realpath(__DIR__ . $modulePath);
}
return $modulePaths;
}
// Return default module paths
return [
realpath(BASE_PATH . '/core/modules')
];
}
/**
* Get an array of all modules
*
* @return array
*/
public function getAllModules(): array
{
$modulePaths = $this->getModulePaths();
return (new ModuleMapper($modulePaths, $this->fileHelper, $this->config))->getAllModuleFolders();
}
/**
* Get a list of the enabled modules
*
* @return array
*/
public function listEnabled(): array
{
$modulePaths = $this->getModulePaths();
$moduleMapper = new ModuleMapper($modulePaths, $this->fileHelper, $this->config);
$modules = [];
if ($this->config->has('modules.enabled')) {
$foundModules = [];
$enabledModules = $this->config->get('modules.enabled');
$modules = $moduleMapper->checkModulesExist($enabledModules);
return $moduleMapper->getModuleClassesFromFileName($modules);
}
$moduleNames = $this->getAllModules();
$modules = $moduleMapper->checkModulesExist($moduleNames);
return $moduleMapper->getModuleClassesFromFileName($modules);
}
/**
* Get Module Services
*
* @return array
*/
public function getModuleServices(): ?array
{
$modules = $this->getEnabled();
$moduleServices = [];
foreach ($modules as $module) {
$moduleServices[] = $module->getServices;
}
}
/**
* Get Module Command
*
* @return array
*/
public function getModuleCommands(): ?array
{
$modules = $this->getEnabled();
$moduleCommands = [];
foreach ($modules as $module) {
//$moduleCommands
}
}
}

View file

@ -1,22 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Module;
use SuiteCRM\Core\Base\Module\Helper\Collection;
/**
* Class ModuleCollection
* @package SuiteCRM\Core\Base\Module
*/
class ModuleCollection extends Collection
{
/**
* Load the module collection
*
* @param array $params list of modules to chose
*/
public function __construct($params = [])
{
return parent::__construct($params);
}
}

View file

@ -1,20 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Module;
/**
* Interface ModuleInterface
* @package SuiteCRM\Core\Base\Module
*/
interface ModuleInterface
{
/**
* @return mixed
*/
public function getName();
/**
* @return mixed
*/
public function getDescription();
}

View file

@ -1,126 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Module;
use SuiteCRM\Core\Base\Helper\File\File;
use SuiteCRM\Core\Base\Config\ParameterCollection;
/**
* Class ModuleMapper
* @package SuiteCRM\Core\Base\Module
*/
class ModuleMapper
{
/**
*
* @var array
*/
protected $filePaths;
/**
*
* @var File
*/
protected $fileHelper;
/**
*
* @var array
*/
protected $moduleConfigParameters;
/**
*
* @var array
*/
protected $enabledModules;
/**
* Setup Object
*
* @param $file_paths
* @param File $file
* @param ParameterCollection $module_config_params
*/
public function __construct($file_paths, File $file, ParameterCollection $module_config_params)
{
$this->filePaths = $file_paths;
$this->fileHelper = $file;
$this->moduleConfigParameters = $module_config_params;
$this->enabledModules = $this->moduleConfigParameters->get('modules.enabled');
}
/**
* Get All Module Folders
*
* @return array
*/
public function getAllModuleFolders(): array
{
return $this->fileHelper->findDirectories($this->filePaths);
}
/**
* Check modules exist out of an array input modules
*
* @param array $modules array of module names to check
* @return array List if found modules
*/
public function checkModulesExist($modules): array
{
$foundModules = [];
if (!empty($modules)) {
foreach ($modules as $module) {
foreach ($this->filePaths as $path) {
if (file_exists($path . '/' . $module . '/' . $module . '.php')) {
$foundModules[] = $path . '/' . $module . '/' . $module . '.php';
}
}
}
}
return $foundModules;
}
/**
* Get all module classes from file name
*
* @param $files
* @return array|bool
*/
public function getModuleClassesFromFileName($files)
{
if (empty($files)) {
return false;
}
$moduleClasses = [];
foreach ($files as $file) {
$file = str_replace('suitecrm/', '', $file);
$parts = explode('/', $file);
$parts = array_splice($parts, 4, count($parts));
$filename = end($parts);
$classname = rtrim($filename, '.php');
$keys = array_keys($parts);
$key = end($keys);
$parts[$key] = $classname;
$parts = array_map('ucfirst', $parts);
$commandClass = 'SuiteCRM\\' . implode('\\', $parts);
$moduleClasses[] = new $commandClass();
}
return $moduleClasses;
}
}

View file

@ -1,34 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Module\Service;
use SuiteCRM\Core\Base\Module\Manager as ModuleManager;
use SuiteCRM\Core\Base\Module\Service\ServiceCollection;
use Symfony\Component\Config\FileLocator;
/**
* Class Manager
* @package SuiteCRM\Core\Base\Module\Service
*/
class Manager
{
protected $serviceList = [];
/**
* Manager constructor.
* @param ModuleManager $moduleManager
*/
public function __construct(ModuleManager $moduleManager)
{
foreach ($moduleManager->listEnabled() as $module) {
$file = new FileLocator();
$service = new $module();
}
return (new ServiceCollection())->load();
}
}

View file

@ -1,22 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Module\Service;
use SuiteCRM\Core\Base\Helper\Data\Collection;
/**
* Class ServiceCollection
* @package SuiteCRM\Core\Base\Module\Service
*/
class ServiceCollection extends Collection
{
/**
* Load the service collection
*
* @param array $services Array of services to change
*/
public function __construct($services = [])
{
return parent::load($services);
}
}

View file

@ -1,25 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Module\Service;
/**
* Interface ServiceFactoryInterface
* @package SuiteCRM\Core\Base\Module\Service
*/
interface ServiceFactoryInterface
{
/**
* @return string
*/
public function getName(): string;
/**
* @return string
*/
public function getDescription(): string;
/**
* @return mixed
*/
public function createService();
}

View file

@ -1,107 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Module\Service;
use SuiteCRM\Core\Base\Helper\File\File;
use SuiteCRM\Core\Base\Module\Manager as ModuleManager;
use SuiteCRM\Core\Base\Config\ParameterCollection;
/**
* Class ServiceMapper
* @package SuiteCRM\Core\Base\Module\Service
*/
class ServiceMapper
{
/**
*
* @var File
*/
protected $fileHelper;
/**
*
* @var array
*/
protected $moduleManager;
/**
*
* @var array
*/
protected $config;
/**
* ServiceMapper constructor.
* @param File $file
* @param ModuleManager $moduleManager
* @param ParameterCollection $config
*/
public function __construct(File $file, ModuleManager $moduleManager, ParameterCollection $config)
{
$this->fileHelper = $file;
$this->moduleManager = $moduleManager;
$this->config = $config;
}
/**
* Get all services enabled in the system
*
* @return ServiceCollection
*/
public function getAllServices(): ServiceCollection
{
$serviceClasses = [];
$filePaths = [];
$enabledModules = $this->moduleManager->getAllModules();
// Get Application Service
if (!empty($enabledModules)) {
foreach ($enabledModules as $module) {
$path = APP_PATH . 'Modules/' . $module . '/Service';
if (file_exists($path)) {
$filePaths[] = $path;
}
}
}
$files = $this->fileHelper->findFiles($filePaths, '/Service.php$/');
if (!empty($files)) {
foreach ($files as $file) {
$parts = explode('/', $file);
$key = array_search('Modules', $parts, true);
$parts = array_splice($parts, $key, count($parts));
$filename = end($parts);
$classname = rtrim($filename, '.php');
$keys = array_keys($parts);
$key = end($keys);
$parts[$key] = $classname;
$serviceClass = 'SuiteCRM\\App\\' . implode('\\', $parts);
$service = new $serviceClass();
$serviceName = $service->getName();
$serviceClasses[$serviceName] = $service->createService();
}
}
// Load in configuration services if they're available
if ($this->config->has('services')) {
foreach ($this->config->get('services') as $serviceName => $serviceFactory) {
$serviceFactory = new $serviceFactory();
$service = $serviceFactory->createService();
$serviceClasses[$serviceName] = $service;
}
}
return new ServiceCollection($serviceClasses);
}
}

View file

@ -1,58 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Storage;
/**
* Class DataCollectionManager
* @package SuiteCRM\Core\Base\Storage
*/
class DataCollectionManager
{
/**
*
* @var array
*/
protected $dataProviders;
/**
*
* @param array $dataProviders
*/
public function __construct($dataProviders)
{
$this->dataProviders = $dataProviders;
}
/**
* Get the Collection Object
*
* @param string $resourceClass
* @param string $operationName
* @param array $context
* @return array
*/
public function getCollection(string $resourceClass, string $operationName = null, array $context = []): array
{
foreach ($this->dataProviders as $dataProvider) {
try {
if ($dataProvider instanceof RestrictedDataProviderInterface
&& !$dataProvider->supports($resourceClass, $operationName, $context)) {
continue;
}
return $dataProvider->getCollection($resourceClass, $operationName, $context);
} catch (ResourceClassNotSupportedException $e) {
@trigger_error(
sprintf(
'Throwing a "%s" in a data provider is deprecated in favor of implementing "%s"',
ResourceClassNotSupportedException::class,
RestrictedDataProviderInterface::class
),
E_USER_DEPRECATED
);
}
}
return [];
}
}

View file

@ -1,37 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Module\Storage;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper;
use Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper;
/**
* Class ImportCommand
* @package SuiteCRM\Core\Base\Module\Storage
*/
class ImportCommand extends \Doctrine\DBAL\Tools\Console\Command\ImportCommand
{
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int|void|null
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$doctrine = $this->getApplication()->getKernel()->getContainer()->get('doctrine');
$em = $doctrine->getEntityManager();
$db = $em->getConnection();
$helperSet = $this->getHelperSet();
$helperSet->set(new ConnectionHelper($db), 'db');
$helperSet->set(new EntityManagerHelper($em), 'em');
parent::execute($input, $output);
}
}

View file

@ -1,25 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Module\Storage;
use Doctrine\ORM\EntityRepository;
/**
* Class Manager
* @package SuiteCRM\Core\Base\Module\Storage
*/
class Manager extends EntityRepository
{
public function __construct()
{
$evm = new \Doctrine\Common\EventManager();
// Table Prefix
$tablePrefix = new \DoctrineExtensions\TablePrefix('prefix_');
$evm->addEventListener(\Doctrine\ORM\Events::loadClassMetadata, $tablePrefix);
$em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config, $evm);
parent::__construct();
}
}

View file

@ -1,49 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Module\Storage;
use \Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
/**
* Class TablePrefix
* @package SuiteCRM\Core\Base\Module\Storage
*/
class TablePrefix
{
protected $prefix = '';
/**
* TablePrefix constructor.
* @param $prefix
*/
public function __construct($prefix)
{
$this->prefix = (string)$prefix;
}
/**
* @param LoadClassMetadataEventArgs $eventArgs
*/
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs): void
{
$classMetadata = $eventArgs->getClassMetadata();
if (!$classMetadata->isInheritanceTypeSingleTable() || $classMetadata->getName(
) === $classMetadata->rootEntityName) {
$classMetadata->setPrimaryTable(
[
'name' => $this->prefix . $classMetadata->getTableName()
]
);
}
foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
if ($mapping['type'] === ClassMetadataInfo::MANY_TO_MANY && $mapping['isOwningSide']) {
$mappedTableName = $mapping['joinTable']['name'];
$classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->prefix . $mappedTableName;
}
}
}
}

View file

@ -1,39 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Module\View;
use \stdClass;
/**
* Class Handler
* @package SuiteCRM\Core\Base\Module\View
*/
class Handler
{
/**
* Render the view file and pass it to the templates
*
* @param string $filename The view files name
* @param array $params Params to pass to view file
* @param string $template
* @return mixed
*/
public function render($filename, $params = [], $template = 'default.json.php')
{
// Allow the view param to work with and with the .php
$filename = (strpos($filename, '.php') !== false) ? $filename : $filename . '.php';
$view = new stdClass();
// Extract the parameters
extract($params);
if (file_exists(__DIR__ . '/template/default.json.php')) {
require __DIR__ . '/template/default.json.php';
} else {
echo $body;
}
}
}

View file

@ -1,3 +0,0 @@
<?php
echo json_encode($view_data, JSON_PRETTY_PRINT);

View file

@ -1,4 +0,0 @@
<?php
header('Content-Type: application/json');
echo json_encode($view_data, JSON_PRETTY_PRINT);

View file

@ -1,91 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Route;
use SuiteCRM\Core\Base\Helper\Data\CollectionInterface;
use SuiteCRM\Core\Base\Http\Request;
/**
* Class DefaultRouter
* @package SuiteCRM\Core\Base\Route
*/
class DefaultRouter implements RouterInterface
{
/**
*
* @var SuiteCRM\Core\Base\Http\Request
*/
private $requestObj;
/**
*
* @var array
*/
private $config;
/**
* DefaultRouter constructor.
* @param Request $request
* @param CollectionInterface $config
*/
public function __construct(Request $request, CollectionInterface $config)
{
$this->requestObj = $request;
$this->config = $config;
}
/**
* @return object
* @throws \Exception
*/
public function load()
{
// Check the correct controller and action is going to load based on the URI
$module = ($this->requestObj->query->has('module')) ? $this->requestObj->query->get('module') : '';
$controller = ($this->requestObj->query->has('controller')) ? $this->requestObj->query->get('controller') : '';
$action = ($this->requestObj->query->has('action')) ? $this->requestObj->query->get('action') : '';
// Run Installer if database config hasn't been configured
if (empty($module)) {
// Check mandatory parameters are set
if (!$this->config->has('app.default_route.module')) {
throw new \RuntimeException('Default module has not been configured.');
}
$module = $this->config->get('app.default_route.module');
}
if (empty($controller)) {
// Check mandatory parameters are set
if (!$this->config->has('app.default_route.controller')) {
throw new \RuntimeException('Default controller has not been configured.');
}
$controller = $this->config->get('app.default_route.controller');
}
if (empty($action)) {
// Check mandatory parameters are set
if (!$this->config->has('app.default_route.action')) {
throw new \RuntimeException('Default action has not been configured.');
}
$action = $this->config->get('app.default_route.action');
}
$format = 'SuiteCRM\Core\Modules\%s\Controller\%s';
$controller = sprintf($format, ucfirst($module), ucfirst($controller));
// run the controller action
return (object)[
'module' => $module,
'controller' => $controller,
'action' => 'action' . ucfirst($action)
];
}
}

View file

@ -1,99 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Route;
use SuiteCRM\Core\Base\Route\RouterInterface;
use SuiteCRM\Core\Base\Helper\Data\CollectionInterface;
use SuiteCRM\Core\Base\Http\Request;
/**
* Class ModRewriteRouter
* @package SuiteCRM\Core\Base\Route
*/
class ModRewriteRouter implements RouterInterface
{
/**
*
* @var SuiteCRM\Core\Base\Http\Request
*/
private $requestObj;
/**
*
* @var array
*/
private $config;
/**
* ModRewriteRouter constructor.
* @param Request $request
* @param CollectionInterface $config
*/
public function __construct(Request $request, CollectionInterface $config)
{
$this->requestObj = $request;
$this->config = $config;
}
/**
* @return object
* @throws \Exception
*/
public function load()
{
// Check the correct controller and action is going to load based on the URI
if ($this->requestObj->query->has('query_string')) {
$uri = explode('/', $this->requestObj->query->get('query_string'));
if (count($uri) === 1) {
array_push($uri, '', '');
} elseif (count($uri) === 2) {
$uri[] = '';
}
[$module, $controller, $action] = $uri;
}
// Run Installer if database config hasn't been configured
if (empty($module)) {
// Check mandatory parameters are set
if (!$this->config->has('app.default_route.module')) {
throw new \RuntimeException('Default module has not been configured.');
}
$module = $this->config->get('app.default_route.module');
}
if (empty($controller)) {
// Check mandatory parameters are set
if (!$this->config->has('app.default_route.controller')) {
throw new \RuntimeException('Default controller has not been configured.');
}
$controller = $this->config->get('app.default_route.controller');
}
if (empty($action)) {
// Check mandatory parameters are set
if (!$this->config->has('app.default_route.action')) {
throw new \RuntimeException('Default action has not been configured.');
}
$action = $this->config->get('app.default_route.action');
}
$format = 'SuiteCRM\Core\Modules\%s\Controller\%s';
$controller = sprintf($format, ucfirst($module), ucfirst($controller));
// run the controller action
return (object)[
'module' => $module,
'controller' => $controller,
'action' => 'action' . ucfirst($action)
];
}
}

View file

@ -1,15 +0,0 @@
<?php
namespace SuiteCRM\Core\Base\Route;
use SuiteCRM\Core\Base\Helper\Input;
use SuiteCRM\Core\Base\Config\ConfigManager;
/**
* Interface RouterInterface
* @package SuiteCRM\Core\Base\Route
*/
interface RouterInterface
{
public function load();
}

View file

@ -1,15 +0,0 @@
<?php
namespace SuiteCRM\Core\Base;
/**
* Interface RunnableInterface
* @package SuiteCRM\Core\Base
*/
interface RunnableInterface
{
/**
* @return mixed
*/
public function run();
}

View file

@ -2,9 +2,9 @@
namespace SuiteCRM\Core\Legacy; namespace SuiteCRM\Core\Legacy;
use SuiteCRM\Core\Base\Config\ParameterCollection; use AuthenticationController;
use Exception;
use SuiteCRM\Core\Legacy\LegacyHandler; use RuntimeException;
/** /**
* Class Authentication * Class Authentication
@ -15,10 +15,10 @@ class Authentication extends LegacyHandler
/** /**
* Set the config * Set the config
* *
* @param ParameterCollection $config * @param $config
* @return $this * @return $this
*/ */
public function setConfig(ParameterCollection $config): self public function setConfig($config): self
{ {
$this->config = $config; $this->config = $config;
@ -33,18 +33,18 @@ class Authentication extends LegacyHandler
* @param $grant_type * @param $grant_type
* *
* @return boolean * @return boolean
* @throws \Exception * @throws Exception
*/ */
public function login($username, $password, $grant_type = 'password'): bool public function login($username, $password, $grant_type = 'password'): bool
{ {
if ($this->runLegacyEntryPoint()) { if ($this->runLegacyEntryPoint()) {
$authController = new \AuthenticationController(); $authController = new AuthenticationController();
$PARAMS = []; $PARAMS = [];
return $authController->login($username, $password, $PARAMS); return $authController->login($username, $password, $PARAMS);
} }
throw new \RuntimeException('Running legacy entry point failed'); throw new RuntimeException('Running legacy entry point failed');
} }
} }

View file

@ -2,15 +2,13 @@
namespace SuiteCRM\Core\Legacy; namespace SuiteCRM\Core\Legacy;
use SuiteCRM\Core\Base\Module\Service\ServiceFactoryInterface;
use SuiteCRM\Core\Legacy\Authentication; use SuiteCRM\Core\Legacy\Authentication;
/** /**
* Class AuthenticationService * Class AuthenticationService
* @package SuiteCRM\Core\Legacy * @package SuiteCRM\Core\Legacy
*/ */
class AuthenticationService implements ServiceFactoryInterface class AuthenticationService
{ {
/** /**
* @return string * @return string

View file

@ -27,7 +27,9 @@ class Navbar extends LegacyHandler
throw new RuntimeException('Running legacy entry point failed'); throw new RuntimeException('Running legacy entry point failed');
} }
/**
* @return array
*/
public function getGroupedNavTabs(): array public function getGroupedNavTabs(): array
{ {
if ($this->runLegacyEntryPoint()) { if ($this->runLegacyEntryPoint()) {

View file

@ -2,13 +2,11 @@
namespace SuiteCRM\Core\Legacy; namespace SuiteCRM\Core\Legacy;
use SuiteCRM\Core\Base\Module\Service\ServiceFactoryInterface;
/** /**
* Class NavbarService * Class NavbarService
* @package SuiteCRM\Core\Legacy * @package SuiteCRM\Core\Legacy
*/ */
class NavbarService implements ServiceFactoryInterface class NavbarService
{ {
/** /**
* @return string * @return string

View file

@ -1,28 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Administration;
use SuiteCRM\Core\Base\Module\ModuleInterface;
/**
* Class Administration
* @package SuiteCRM\Core\Modules\Administration
*/
class Administration implements ModuleInterface
{
/**
* @return string
*/
public function getName(): string
{
return 'Administration Module';
}
/**
* @return string
*/
public function getDescription(): string
{
return 'This module will allow administrators to configure the system';
}
}

View file

@ -0,0 +1,12 @@
<?php
namespace SuiteCRM\Core\Modules\Administration;
use Symfony\Component\HttpKernel\Bundle\Bundle;
/**
* Class Administration
* @package SuiteCRM\Core\Modules\Administration
*/
class AdministrationBundle extends Bundle
{
}

View file

@ -1,71 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Administration\Cli\Composer;
use SuiteCRM\Core\Base\Cli\SuiteCommand;
use SuiteCRM\Core\Base\Helper\File\File;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputOption;
/**
* Class ComposerInstallCommand
* @package SuiteCRM\Core\Modules\Administration\Cli\Setup
*/
class ComposerInstallCommand extends SuiteCommand
{
protected $file;
protected $config;
/**
* ComposerInstallCommand constructor.
* @param array $config
*/
public function __construct($config = [])
{
parent::__construct();
$this->config = $config;
$this->file = new File();
}
protected function configure(): void
{
$this
->setName('composer:install')
->setDescription('Install core composer dependencies')
->setHelp('This command will install all required project dependencies')
->addOption(
'nodev',
'',
InputOption::VALUE_NONE,
'Install without dev packages'
);
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int|void|null
*/
public function execute(InputInterface $input, OutputInterface $output)
{
$currentDir = __DIR__ . '/../../../../../';
$optionValue = $input->getOption('nodev');
$noDev = ($optionValue !== false);
if ($noDev === true) {
shell_exec('composer install --no-dev');
chdir($currentDir . 'legacy');
shell_exec('composer install --no-dev');
chdir($currentDir);
}
shell_exec('composer install');
chdir($currentDir . 'legacy');
shell_exec('composer install');
chdir($currentDir);
}
}

View file

@ -1,53 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Administration\Cli\Composer;
use SuiteCRM\Core\Base\Cli\SuiteCommand;
use SuiteCRM\Core\Base\Helper\File\File;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Class ComposerUpdateCommand
* @package SuiteCRM\Core\Modules\Administration\Cli\Setup
*/
class ComposerUpdateCommand extends SuiteCommand
{
protected $file;
protected $config;
/**
* ComposerUpdateCommand constructor.
* @param array $config
*/
public function __construct($config = [])
{
parent::__construct();
$this->config = $config;
$this->file = new File();
}
protected function configure(): void
{
$this
->setName('composer:update')
->setDescription('Update core composer dependencies')
->setHelp('This command will install all required project dependencies');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int|void|null
*/
public function execute(InputInterface $input, OutputInterface $output)
{
$currentDir = __DIR__ . '/../../../../../';
shell_exec('composer update');
chdir($currentDir . 'legacy');
shell_exec('composer update');
chdir($currentDir);
}
}

View file

@ -1,63 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Administration\Cli\Modules;
use \SuiteCRM\Core\Base\Module\Manager as ModuleManager;
use \SuiteCRM\Core\Base\Config\Manager as ConfigManager;
use \SuiteCRM\Core\Base\Helper\File\File;
use \SuiteCRM\Core\Base\Cli\SuiteCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
/**
* Class ListModulesCommand
* @package SuiteCRM\Core\Modules\Administration\Cli\Modules
*/
class ListModulesCommand extends SuiteCommand
{
protected function configure()
{
$this
->setName('core:modules:list-all')
->setDescription('List Application Modules')
->setHelp('This command will list the possible Application Modules.');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int|void|null
* @throws \Exception
*/
public function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
$io->success('List of all modules.');
$parameterCollection = (new ConfigManager())->loadFiles(
[
BASE_PATH . '/core/base/Config/modules.config.yml'
]
);
$fileHelper = new File();
$modules = (new ModuleManager($parameterCollection, $fileHelper))->listEnabled();
$tableHeaders = [
['Module Name', 'Module Description']
];
for ($i = 0, $iMax = count($modules); $i < $iMax; $i++) {
$moduleData[$i] = [
$modules[$i]->getName(),
$modules[$i]->getDescription()
];
}
$io->table($tableHeaders, $moduleData);
}
}

View file

@ -1,33 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Administration\Cli\Repair;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use SuiteCRM\Core\Base\Cli\SuiteCommand;
/**
* Class QuickRepairRebuildCommand
* @package SuiteCRM\Core\Modules\Administration\Cli\Repair
*/
class QuickRepairRebuildCommand extends SuiteCommand
{
// The name of the command
protected function configure()
{
$this
->setName('admin:repair:quick-repair-rebuild')
->setDescription('Run Quick Repair and Rebuild')
->setHelp('This command allows you to run the repair and rebuild.');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int|void|null
*/
public function execute(InputInterface $input, OutputInterface $output)
{
}
}

View file

@ -1,36 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Administration\Cli\Users;
use SuiteCRM\Core\Base\Cli\SuiteCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Class AddNewUserCommand
* @package SuiteCRM\Core\Modules\Administration\Cli\Users
*/
class AddNewUserCommand extends SuiteCommand
{
// The name of the command
protected function configure()
{
$this
->setName('admin:add-new-user')
->setDescription('Add new user to the system')
->setHelp('This command allows you to run the add new user to the system.');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int|void
*/
public function execute(InputInterface $input, OutputInterface $output)
{
/**
* @todo : Create input for user before creating
*/
}
}

View file

@ -1,37 +0,0 @@
SuiteCRM\Core\Modules\Users\Entity\OAuthAccessToken:
type: entity
table: oauth_access_tokens
repositoryClass: SuiteCRM\Core\Modules\Users\Storage\OAuthAccessTokenStorage
id:
id:
type: integer
generator:
strategy: AUTO
fields:
token:
type: string
max_length: 40
unique: true
client_id:
type: integer
user_id:
type: integer
nullable: true
expires:
type: datetime
#columnDefinition: TIMESTAMP
scope:
type: string
max_length: 50
nullable: true
manyToOne:
client:
targetEntity: SuiteCRM\Core\Modules\Users\Entity\OAuthClient
joinColumn:
name: client_id
referencedColumnName: id
user:
targetEntity: SuiteCRM\Core\Modules\Users\Entity\OAuthUser
joinColumn:
name: user_id
referencedColumnName: id

View file

@ -1,42 +0,0 @@
SuiteCRM\Core\Modules\Users\Entity\OAuthAuthorizationCode:
type: entity
table: oauth_authorisation_codes
repositoryClass: SuiteCRM\Core\Modules\Users\Storage\OAuthAuthorizationCodeStorage
id:
id:
type: integer
generator:
strategy: AUTO
fields:
code:
type: string
max_length: 40
unique: true
client_id:
type: integer
user_id:
type: integer
nullable: true
expires:
type: datetime
redirect_uri:
type: string
max_length: 200
scope:
type: string
max_length: 50
nullable: true
id_token:
type: string
length: 1000
manyToOne:
client:
targetEntity: SuiteCRM\Core\Modules\Users\Entity\OAuthClient
joinColumn:
name: client_id
referencedColumnName: id
user:
targetEntity: SuiteCRM\Core\Modules\Users\Entity\OAuthUser
joinColumn:
name: user_id
referencedColumnName: id

View file

@ -1,22 +0,0 @@
SuiteCRM\Core\Modules\Users\Entity\OAuthClient:
type: entity
table: oauth_client
repositoryClass: SuiteCRM\Core\Modules\Users\Storage\OAuthClientStorage
id:
id:
type: integer
generator:
strategy: AUTO
fields:
client_identifier:
type: string
max_length: 50
unique: true
client_secret:
type: string
max_length: 20
default: ""
redirect_uri:
type: string
max_length: 255
default: ""

View file

@ -1,22 +0,0 @@
SuiteCRM\Core\Modules\Users\Entity\OAuthPublicKey:
type: entity
table: oauth_public_key
repositoryClass: SuiteCRM\Core\Modules\Users\Storage\OAuthPublicKeyStorage
id:
id:
type: integer
generator:
strategy: AUTO
fields:
public_key:
type: string
length: 2000
private_key:
type: string
length: 2000
manyToOne:
client:
targetEntity: SuiteCRM\Core\Modules\Users\Entity\OAuthClient
joinColumn:
name: client_id
referencedColumnName: id

View file

@ -1,37 +0,0 @@
SuiteCRM\Core\Modules\Users\Entity\OAuthRefreshToken:
type: entity
table: oauth_refresh_tokens
repositoryClass: SuiteCRM\Core\Modules\Users\Storage\OAuthRefreshTokenStorage
id:
id:
type: integer
generator:
strategy: AUTO
fields:
refresh_token:
refresh_token: string
max_length: 40
unique: true
client_id:
type: integer
user_id:
type: integer
nullable: true
expires:
type: datetime
column: expires
scope:
type: string
max_length: 50
nullable: true
manyToOne:
client:
targetEntity: SuiteCRM\Core\Modules\Users\Entity\OAuthClient
joinColumn:
name: client_id
referencedColumnName: id
user:
targetEntity: SuiteCRM\Core\Modules\Users\Entity\OAuthUser
joinColumn:
name: user_id
referencedColumnName: id

View file

@ -1,20 +0,0 @@
SuiteCRM\Core\Modules\Users\Entity\OAuthUser:
type: entity
table: oauth_users
repositoryClass: SuiteCRM\Core\Modules\Users\Storage\OAuthUserStorage
id:
id:
type: integer
generator:
strategy: AUTO
fields:
username:
unique: true
type: string
column: user_name
password:
type: string
column: user_hash
indexes:
user_name_index:
columns: [ user_name ]

View file

@ -1,15 +0,0 @@
SuiteCRM\Core\Modules\Users\Entity\OAuthUserClaims:
type: entity
table: oauth_user_claims
repositoryClass: SuiteCRM\Core\Modules\Users\Storage\OAuthUserClaimsStorage
id:
id:
type: integer
generator:
strategy: AUTO
manyToOne:
user:
targetEntity: SuiteCRM\Core\Modules\Users\Entity\OAuthUser
joinColumn:
name: user_id
referencedColumnName: id

View file

@ -1,213 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Controller;
use SuiteCRM\Core\Base\Module\Controller as SuiteController;
use \OAuth2\Server as OAuth2Server;
use \OAuth2\Response as OAuth2Response;
use \OAuth2\GrantType\UserCredentials as OAuth2GrantTypeUserCredentials;
use \OAuth2\GrantType\RefreshToken as OAuth2GrantTypeRefreshToken;
use \OAuth2\ResponseType\AccessToken as OAuth2ResponseTypeAccessToken;
use SuiteCRM\Core\Modules\Users\Entity\OAuthAuthorizationCode;
class Oauth extends SuiteController
{
/**
* @return \SuiteCRM\Core\Base\Http\Response
* @throws \Exception
*/
public function actionLogin()
{
$request = \OAuth2\HttpFoundationBridge\Request::createFromRequest($this->requestObj);
$response = new OAuth2Response();
// Load authentication service
$authenticationService = $this->getService('users.authentication');
// Load config parameters
$authenticationService->setConfig($this->config);
// Get params
$username = $this->requestObj->request->get('username');
$password = $this->requestObj->request->get('password');
if ($authenticationService->login($username, $password)) {
// Get storage classes
$clientStorage = $this->getStorage('users.oAuthClient');
$userStorage = $this->getStorage('users.oAuthUser');
$accessTokenStorage = $this->getStorage('users.oAuthAccessToken');
$authorizationCodeStorage = $this->getStorage('users.oAuthAuthorizationCode');
$refreshTokenStorage = $this->getStorage('users.oAuthRefreshToken');
$storage = [
'client_credentials' => $clientStorage,
'user_credentials' => $userStorage,
'access_token' => $accessTokenStorage,
'authorization_code' => $authorizationCodeStorage,
'refresh_token' => $refreshTokenStorage,
];
$config = [];
// Set up oauth2 server
$server = new OAuth2Server(
$storage,
$config
);
// Grant token with client details are in system
if (!$token = $server->grantAccessToken($request, $response)) {
$response->send();
die();
}
// Output token in json format
$this->responseObj->headers->set('Content-Type', 'application/json');
return $this->responseObj
->setContent(
json_encode($token)
)
->send();
}
// Response with unauthorised.
$this->responseObj->headers->set('Content-Type', 'application/json');
return $this->responseObj
->setContent(
json_encode(
[
'message' => 'Authentication: Unauthorised',
'code' => '401',
]
)
)
->setStatusCode(401)
->send();
}
public function actionLogout(): void
{
$request = \OAuth2\HttpFoundationBridge\Request::createFromRequest($this->requestObj);
$clientStorage = $this->getStorage('users.oAuthClient');
$userStorage = $this->getStorage('users.oAuthUser');
$accessTokenStorage = $this->getStorage('users.oAuthAccessToken');
$authorizationCodeStorage = $this->getStorage('users.oAuthAuthorizationCode');
$refreshTokenStorage = $this->getStorage('users.oAuthRefreshToken');
$storage = [
'client_credentials' => $clientStorage,
'user_credentials' => $userStorage,
'access_token' => $accessTokenStorage,
'authorization_code' => $authorizationCodeStorage,
'refresh_token' => $refreshTokenStorage,
];
$config = [];
$server = new OAuth2Server(
$storage,
$config
);
// Handle a request to a resource and authenticate the access token
if (!$server->verifyResourceRequest($request)) {
var_dump($server->getResponse());
die();
}
$accessToken = $this->requestObj->request->get('access_token');
$refreshAccessToken = $this->requestObj->request->get('refresh_token');
$accessTokenStorage->expireToken($accessToken);
$refreshTokenStorage->expireToken($refreshAccessToken);
echo json_encode(['success' => true, 'message' => 'Logout Success']);
}
public function refreshToken(): void
{
}
public function actionAccessToken(): void
{
// $config = array();
//
// $requestObj = \OAuth2\HttpFoundationBridge\Request::createFromRequest($this->requestObj);
//
// $clientStorage = $this->getStorage('users.oAuthClient');
// $userStorage = $this->getStorage('users.oAuthUser');
// $accessTokenStorage = $this->getStorage('users.oAuthAccessToken');
// $authorizationCodeStorage = $this->getStorage('users.oAuthAuthorizationCode');
// $refreshTokenStorage = $this->getStorage('users.oAuthRefreshToken');
// $publicKeyStorage = $this->getStorage('users.oAuthPublicKey');
//
// $storage = array(
// 'client_credentials' => $clientStorage,
// 'user_credentials' => $userStorage,
// 'access_token' => $accessTokenStorage,
// 'authorization_code' => $authorizationCodeStorage,
// 'refresh_token' => $refreshTokenStorage
// );
//
// $grantType = $requestObj->request->get('grant_type');
//
// if ($grantType == 'refresh_token') {
// // Set default refresh token parameters
// $refreshTokenLifetime = 10;
// $alwaysIssueNewRefreshToken = false;
//
// // Get config refresh token parameters if set
// if ($this->config->has('app.refresh_token_lifetime')) {
// $refreshAccessToken = (int) $this->config->get('app.refresh_token_lifetime');
// }
//
// if ($this->config->has('app.always_issue_new_refresh_token')) {
// $alwaysIssueNewRefreshToken = (boolean) $this->config->get('app.always_issue_new_refresh_token');
// }
//
// $config = array(
// 'always_issue_new_refresh_token' => $alwaysIssueNewRefreshToken,
// 'refresh_token_lifetime' => $refreshTokenLifetime,
// );
// }
//
// $server = new OAuth2Server($storage, $config);
//
// if ($grantType == 'password') {
//// $username = $params['user_name'];
//// $password = $params['user_hash'];
//
// // Add the grant type to your OAuth server
// $server->addGrantType(new OAuth2GrantTypeUserCredentials($userStorage));
//
// $config = array();
// } elseif ($grantType == "refresh_token") {
// // Add the grant type to your OAuth server
//
// $objectGrantType = new OAuth2GrantTypeRefreshToken($refreshTokenStorage);
//
// $server->addGrantType($objectGrantType);
//
// // The refresh token
// $accessToken = new OAuth2ResponseTypeAccessToken($accessTokenStorage, $refreshTokenStorage, array(
// 'refresh_token_lifetime' => $refreshTokenLifetime,
// ));
//
// $server = new OAuth2Server($storage, $config, [$objectGrantType], array($accessToken));
// } else {
// throw new \Exception('Grant type - not supported.');
// }
//
// $tokenResponse = $server->handleTokenRequest($requestObj);
//
// $statusCode = $tokenResponse->getStatusCode();
// $parameters = $tokenResponse->getParameters();
//
// return $tokenResponse->send();
}
}

View file

@ -1,31 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Entity;
class EncryptableField
{
protected $hashOptions = ['cost' => 11];
/**
* @param $value
* @return mixed
*/
protected function encryptField($value)
{
return $value;
// return password_hash(
// $value, PASSWORD_BCRYPT, $this->hashOptions);
}
/**
* @param $encryptedValue
* @param $value
* @return bool
*/
protected function verifyEncryptedFieldValue($encryptedValue, $value): bool
{
return ($encryptedValue == $value);
//return password_verify($value, $encryptedValue);
}
}

View file

@ -1,248 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Entity;
/**
* OAuthAccessToken
*/
class OAuthAccessToken
{
/**
* @var int
*/
private $id;
/**
* @var string
*/
private $token;
/**
* @var string
*/
private $client_id;
/**
* @var string
*/
private $user_id;
/**
* @var timestamp
*/
private $expires;
/**
* @var string
*/
private $scope;
/**
* @var \YourNamespace\Entity\OAuthClient
*/
private $client;
/**
* @var \YourNamespace\Entity\OAuthUser
*/
private $user;
/**
* Get id
*
* @return int
*/
public function getId(): int
{
return $this->id;
}
/**
* Set token
*
* @param string $token
* @return OAuthAccessToken
*/
public function setToken($token): OAuthAccessToken
{
$this->token = $token;
return $this;
}
/**
* Get token
*
* @return string
*/
public function getToken(): string
{
return $this->token;
}
/**
* Set client_id
*
* @param string $clientId
* @return OAuthAccessToken
*/
public function setClientId($clientId): OAuthAccessToken
{
$this->client_id = $clientId;
return $this;
}
/**
* Get client_id
*
* @return string
*/
public function getClientId(): string
{
return $this->client_id;
}
/**
* Set user_id
*
* @param $userId
* @return OAuthAccessToken
*/
public function setUserId($userId): OAuthAccessToken
{
$this->user_id = $userId;
return $this;
}
/**
* Get user_identifier
*
* @return string
*/
public function getUserId(): string
{
return $this->user_id;
}
/**
* Set expires
*
* @param \DateTime $expires
* @return OAuthAccessToken
*/
public function setExpires($expires): OAuthAccessToken
{
$this->expires = $expires;
return $this;
}
/**
* Get expires
*
* @return \DateTime
*/
public function getExpires(): \DateTime
{
return $this->expires;
}
/**
* Set scope
*
* @param string $scope
* @return OAuthAccessToken
*/
public function setScope($scope): OAuthAccessToken
{
$this->scope = $scope;
return $this;
}
/**
* Get scope
*
* @return string
*/
public function getScope(): string
{
return $this->scope;
}
/**
* Set client
*
* @param SuiteCRM\Core\Modules\Users\Entity\OAuthClient $client
* @return OAuthAccessToken
*/
public function setClient(SuiteCRM\Core\Modules\Users\Entity\OAuthClient $client = null): OAuthAccessToken
{
$this->client = $client;
return $this;
}
/**
* Get client
*
* @return SuiteCRM\Core\Modules\Users\Entity\OAuthClient
*/
public function getClient(): SuiteCRM\Core\Modules\Users\Entity\OAuthClient
{
return $this->client;
}
/**
* @param $params
* @return OAuthAccessToken
*/
public static function fromArray($params): OAuthAccessToken
{
$token = new self();
foreach ($params as $property => $value) {
$token->$property = $value;
}
return $token;
}
/**
* Set user
*
* @param SuiteCRM\Core\Modules\Users\Entity\OAuthUser $user
* @return OAuthRefreshToken
*/
public function setUser(SuiteCRM\Core\Modules\Users\Entity\OAuthUser $user = null): OAuthRefreshToken
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* @return SuiteCRM\Core\Modules\Users\Entity\OAuthUser
*/
public function getUser(): SuiteCRM\Core\Modules\Users\Entity\OAuthUser
{
return $this->client;
}
/**
* @return array
*/
public function toArray(): array
{
return [
'token' => $this->token,
'client_id' => $this->client_id,
'user_id' => $this->user_id,
'expires' => $this->expires,
'scope' => $this->scope,
];
}
}

View file

@ -1,303 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Entity;
class OAuthAuthorizationCode
{
/**
* @var int
*/
private $id;
/**
* @var string
*/
private $code;
/**
* @var string
*/
private $client_id;
/**
* @var string
*/
private $user_id;
/**
* @var \DateTime
*/
private $expires;
/**
* @var string
*/
private $redirect_uri;
/**
* @var string
*/
private $scope;
/**
* @var string
*/
private $id_token;
/**
* @var OAuthClient
*/
private $client;
/**
* @var OAuthUser
*/
private $user;
/**
* Get id
*
* @return int
*/
public function getId(): int
{
return $this->id;
}
/**
* Set code
*
* @param string $code
* @return OAuthAuthorizationCode
*/
public function setCode($code): OAuthAuthorizationCode
{
$this->code = $code;
return $this;
}
/**
* Get code
*
* @return string
*/
public function getCode(): string
{
return $this->code;
}
/**
* Set client_id
*
* @param string $clientId
* @return OAuthAuthorizationCode
*/
public function setClientId($clientId): OAuthAuthorizationCode
{
$this->client_id = $clientId;
return $this;
}
/**
* Get client_id
*
* @return string
*/
public function getClientId(): string
{
return $this->client_id;
}
/**
* Set user_id
*
* @param $userId
* @return OAuthAuthorizationCode
*/
public function setUserId($userId): OAuthAuthorizationCode
{
$this->user_id = $userId;
return $this;
}
/**
* Get user_identifier
*
* @return string
*/
public function getUserId(): string
{
return $this->user_id;
}
/**
* Set expires
*
* @param \DateTime $expires
* @return OAuthAuthorizationCode
*/
public function setExpires($expires): OAuthAuthorizationCode
{
$this->expires = $expires;
return $this;
}
/**
* Get expires
*
* @return \DateTime
*/
public function getExpires(): \DateTime
{
return $this->expires;
}
/**
* Set redirect_uri
*
* @param string $redirectUri
* @return OAuthAuthorizationCode
*/
public function setRedirectUri($redirectUri): OAuthAuthorizationCode
{
$this->redirect_uri = $redirectUri;
return $this;
}
/**
* Get redirect_uri
*
* @return string
*/
public function getRedirectUri(): string
{
return $this->redirect_uri;
}
/**
* Set scope
*
* @param string $scope
* @return OAuthAuthorizationCode
*/
public function setScope($scope): OAuthAuthorizationCode
{
$this->scope = $scope;
return $this;
}
/**
* Get scope
*
* @return string
*/
public function getScope(): string
{
return $this->scope;
}
/**
* Set client
*
* @param OAuthClient $client
* @return OAuthAuthorizationCode
*/
public function setClient(OAuthClient $client = null): OAuthAuthorizationCode
{
$this->client = $client;
return $this;
}
/**
* Get client
*
* @return OAuthClient
*/
public function getClient(): OAuthClient
{
return $this->client;
}
/**
* Set user
*
* @param OAuthUser $user
* @return OAuthRefreshToken
*/
public function setUser(OAuthUser $user = null): OAuthRefreshToken
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* @return \YourNamespace\Entity\OAuthUser
*/
public function getUser(): \YourNamespace\Entity\OAuthUser
{
return $this->client;
}
/**
* @return array
*/
public function toArray(): array
{
return [
'code' => $this->code,
'client_id' => $this->client_id,
'user_id' => $this->user_id,
'expires' => $this->expires,
'scope' => $this->scope,
];
}
/**
* @param $params
* @return OAuthAuthorizationCode
*/
public static function fromArray($params): OAuthAuthorizationCode
{
$code = new self();
foreach ($params as $property => $value) {
$code->$property = $value;
}
return $code;
}
/**
* Get the value of Id Token
*
* @return string
*/
public function getIdToken(): string
{
return $this->id_token;
}
/**
* Set the value of Id Token
*
* @param string id_token
*
* @return self
*/
public function setIdToken($id_token): self
{
$this->id_token = $id_token;
return $this;
}
}

View file

@ -1,195 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Entity;
use SuiteCRM\Core\Modules\Users\Entity\EncryptableField;
class OAuthClient extends EncryptableField
{
/**
* @var int
*/
private $id;
/**
* @var string
*/
private $client_identifier;
/**
* @var string
*/
private $client_secret;
/**
* @var string
*/
private $redirect_uri = '';
/**
* dds
* @var [type]
*/
private $status;
/**
* OAuthClient constructor.
* @param array $row
* @throws \Exception
*/
public function __construct($row = [])
{
foreach ($row as $key => $val) {
if (property_exists($this, $key)) {
$this->{$key} = $val;
}
}
if ($this->id == 0) {
$this->created_date = new \DateTime();
}
$this->modified_date = new \DateTime();
}
/**
* Get id
*
* @return int
*/
public function getId(): int
{
return $this->id;
}
/**
* Set client_identifier
*
* @param string $clientIdentifier
* @return OAuthClient
*/
public function setClientIdentifier($clientIdentifier): OAuthClient
{
$this->client_identifier = $clientIdentifier;
return $this;
}
/**
* Get client_identifier
*
* @return string
*/
public function getClientIdentifier(): string
{
return $this->client_identifier;
}
/**
* Set client_secret
*
* @param string $clientSecret
* @return OAuthClient
*/
public function setClientSecret($clientSecret): OAuthClient
{
$this->client_secret = $this->encryptField($clientSecret);
return $this;
}
/**
* Get client_secret
*
* @return string
*/
public function getClientSecret(): string
{
return $this->client_secret;
}
/**
* Verify client's secret
*
* @param $clientSecret
* @return Boolean
*/
public function verifyClientSecret($clientSecret): bool
{
return $this->verifyEncryptedFieldValue($this->getClientSecret(), $clientSecret);
}
/**
* Set redirect_uri
*
* @param string $redirectUri
* @return OAuthClient
*/
public function setRedirectUri($redirectUri): OAuthClient
{
$this->redirect_uri = $redirectUri;
return $this;
}
/**
* Get redirect_uri
*
* @return string
*/
public function getRedirectUri(): string
{
return $this->redirect_uri;
}
/**
* @return array
*/
public function toArray(): array
{
return [
'client_id' => $this->client_identifier,
'client_secret' => $this->client_secret,
'redirect_uri' => $this->redirect_uri,
];
}
/**
* Set the value of Id
*
* @param int id
*
* @return self
*/
public function setId($id): self
{
$this->id = $id;
return $this;
}
/**
* Get the value of Status
*
* @return mixed
*/
public function getStatus()
{
return $this->status;
}
/**
* Set the value of Status
*
* @param mixed status
*
* @return self
*/
public function setStatus($status): self
{
$this->status = $status;
return $this;
}
}

View file

@ -1,127 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Entity;
class OAuthPublicKey
{
/**
* @var integar
*/
private $id;
/**
* @var string
*/
private $public_key;
/**
* @var string
*/
private $private_key;
/**
* @var string
*/
private $client_id;
/**
* @var SuiteCRM\Core\Modules\Users\Entity\OAuthClient
*/
private $client;
/**
* Get the value of Id
*
* @return integar
*/
public function getId(): integar
{
return $this->id;
}
/**
* Set the value of Id
*
* @param integar id
*
* @return self
*/
public function setId(integar $id): self
{
$this->id = $id;
return $this;
}
/**
* Get the value of Public Key
*
* @return string
*/
public function getPublicKey(): string
{
return $this->public_key;
}
/**
* Set the value of Public Key
*
* @param string public_key
*
* @return self
*/
public function setPublicKey($public_key): self
{
$this->public_key = $public_key;
return $this;
}
/**
* Get the value of Private Key
*
* @return string
*/
public function getPrivateKey(): string
{
return $this->private_key;
}
/**
* Set the value of Private Key
*
* @param string private_key
*
* @return self
*/
public function setPrivateKey($private_key): self
{
$this->private_key = $private_key;
return $this;
}
/**
* Set client
*
* @param OAuthClient $client
* @return OAuthAuthorizationCode
*/
public function setClient(OAuthClient $client = null): OAuthAuthorizationCode
{
$this->client = $client;
return $this;
}
/**
* Get client
*
* @return \YourNamespace\Entity\OAuthClient
*/
public function getClient(): \YourNamespace\Entity\OAuthClient
{
return $this->client;
}
}

View file

@ -1,245 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Entity;
class OAuthRefreshToken
{
/**
* @var int
*/
private $id;
/**
* @var string
*/
private $refresh_token;
/**
* @var string
*/
private $client_id;
/**
* @var string
*/
private $user_id;
/**
* @var timestamp
*/
private $expires;
/**
* @var string
*/
private $scope;
/**
* @var SuiteCRM\Core\Modules\Users\Entity\OAuthClient
*/
private $client;
/**
* @var SuiteCRM\Core\Modules\Users\Entity\OAuthUser
*/
private $user;
/**
* Get id
*
* @return int
*/
public function getId(): int
{
return $this->id;
}
/**
* Set refresh_token
*
* @param string $refresh_token
* @return OAuthRefreshToken
*/
public function setRefreshToken($refresh_token): OAuthRefreshToken
{
$this->refresh_token = $refresh_token;
return $this;
}
/**
* Get refresh_token
*
* @return string
*/
public function getRefreshToken(): string
{
return $this->refresh_token;
}
/**
* Set client_id
*
* @param string $clientId
* @return OAuthRefreshToken
*/
public function setClientId($clientId): OAuthRefreshToken
{
$this->client_id = $clientId;
return $this;
}
/**
* Get client_id
*
* @return string
*/
public function getClientId(): string
{
return $this->client_id;
}
/**
* Set user_id
*
* @param $userId
* @return OAuthRefreshToken
*/
public function setUserId($userId): OAuthRefreshToken
{
$this->user_id = $userId;
return $this;
}
/**
* Get user_identifier
*
* @return string
*/
public function getUserId(): string
{
return $this->user_id;
}
/**
* Set expires
*
* @param \DateTime $expires
* @return OAuthRefreshToken
*/
public function setExpires($expires): OAuthRefreshToken
{
$this->expires = $expires;
return $this;
}
/**
* Get expires
*
* @return \DateTime
*/
public function getExpires(): \DateTime
{
return $this->expires;
}
/**
* Set scope
*
* @param string $scope
* @return OAuthRefreshToken
*/
public function setScope($scope): OAuthRefreshToken
{
$this->scope = $scope;
return $this;
}
/**
* Get scope
*
* @return string
*/
public function getScope(): string
{
return $this->scope;
}
/**
* Set client
*
* @param SuiteCRM\Core\Modules\Users\Entity\OAuthClient $client
* @return OAuthRefreshToken
*/
public function setClient(SuiteCRM\Core\Modules\Users\Entity\OAuthClient $client = null): OAuthRefreshToken
{
$this->client = $client;
return $this;
}
/**
* Get client
*
* @return SuiteCRM\Core\Modules\Users\Entity\OAuthClient
*/
public function getClient(): SuiteCRM\Core\Modules\Users\Entity\OAuthClient
{
return $this->client;
}
/**
* Set user
*
* @param SuiteCRM\Core\Modules\Users\Entity\OAuthUser $user
* @return OAuthRefreshToken
*/
public function setUser(SuiteCRM\Core\Modules\Users\Entity\OAuthUser $user = null): OAuthRefreshToken
{
$this->user = $user;
return $this;
}
/**
* Get user
*
* @return SuiteCRM\Core\Modules\Users\Entity\OAuthUser
*/
public function getUser(): SuiteCRM\Core\Modules\Users\Entity\OAuthUser
{
return $this->client;
}
/**
* @return array
*/
public function toArray(): array
{
return [
'refresh_token' => $this->refresh_token,
'client_id' => $this->client_id,
'user_id' => $this->user_id,
'expires' => $this->expires,
'scope' => $this->scope,
];
}
/**
* @param $params
* @return OAuthRefreshToken
*/
public static function fromArray($params): OAuthRefreshToken
{
$token = new self();
foreach ($params as $property => $value) {
$token->$property = $value;
}
return $token;
}
}

View file

@ -1,108 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Entity;
use SuiteCRM\Core\Modules\Users\Entity\EncryptableField;
class OAuthUser extends EncryptableField
{
/**
* @var int
*/
private $id;
/**
* @var string
*/
private $username;
/**
* @var string
*/
private $password;
/**
* @var string
*/
private $session_id;
/**
* Get id
*
* @return int
*/
public function getId(): int
{
return $this->id;
}
/**
* Set username
*
* @param $username
* @return User
*/
public function setUsername($username): User
{
$this->username = $username;
return $this;
}
/**
* Get username
*
* @return string
*/
public function getUsername(): string
{
return $this->username;
}
/**
* Set password
*
* @param string $password
* @return User
*/
public function setPassword($password): User
{
$this->password = $this->encryptField($password);
return $this;
}
/**
* Get password
*
* @return string
*/
public function getPassword(): string
{
return $this->password;
}
/**
* Verify user's password
*
* @param string $password
* @return Boolean
*/
public function verifyPassword($password): bool
{
return $this->verifyEncryptedFieldValue($this->getPassword(), $password);
}
/**
* Get OAuthUser object in array format
*
* @return array
*/
public function toArray(): array
{
return [
'user_id' => $this->id,
'scope' => null,
];
}
}

View file

@ -1,99 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Entity;
class OAuthUserClaims
{
/**
* @var string
*/
private $id;
/**
* @var string
*/
private $id_token;
/**
* @var string
*/
private $user_id;
/**
* @var string
*/
private $user;
/**
* Get the value of Id
*
* @return string
*/
public function getId(): string
{
return $this->id;
}
/**
* Set the value of Id
*
* @param string id
*
* @return self
*/
public function setId($id): self
{
$this->id = $id;
return $this;
}
/**
* Get the value of Id Token
*
* @return string
*/
public function getIdToken(): string
{
return $this->id_token;
}
/**
* Set the value of Id Token
*
* @param string id_token
*
* @return self
*/
public function setIdToken($id_token): self
{
$this->id_token = $id_token;
return $this;
}
/**
* Get the value of User Id
*
* @return string
*/
public function getUserId(): string
{
return $this->user_id;
}
/**
* Set the value of User Id
*
* @param string user_id
*
* @return self
*/
public function setUserId($user_id): self
{
$this->user_id = $user_id;
return $this;
}
}

View file

@ -1,13 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Entity;
use SuiteCRM\Core\Module\Controller as SuiteController;
class UserProfile
{
/**
* @var int
*/
private $id;
}

View file

@ -1,11 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Helper;
class Authentication
{
public function login(): void
{
// Authentication stub
}
}

View file

@ -1,33 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Service;
use SuiteCRM\Core\Base\Module\Service\ServiceFactoryInterface;
use SuiteCRM\Core\Modules\Users\Helper\Authentication;
class AuthenticationService implements ServiceFactoryInterface
{
/**
* @return string
*/
public function getName(): string
{
return 'users.authentication';
}
/**
* @return string
*/
public function getDescription(): string
{
return 'This service will deal with legacy authentication';
}
/**
* @return Authentication
*/
public function createService(): Authentication
{
return new Authentication();
}
}

View file

@ -1,91 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Storage;
use SuiteCRM\Core\Modules\Users\Entity\OAuthAccessToken;
use Doctrine\ORM\EntityRepository;
use OAuth2\Storage\AccessTokenInterface;
class OAuthAccessTokenStorage extends EntityRepository implements AccessTokenInterface
{
/**
* @param string $oauthToken
* @return array|object|null
*/
public function getAccessToken($oauthToken)
{
$token = $this->findOneBy(['token' => $oauthToken]);
if ($token) {
$token = $token->toArray();
$token['expires'] = $token['expires']->getTimestamp();
}
return $token;
}
/**
* @param string $oauthToken
* @param mixed $clientIdentifier
* @param mixed $user_id
* @param int $expires
* @param null $scope
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
*/
public function setAccessToken($oauthToken, $clientIdentifier, $user_id, $expires, $scope = null)
{
$client = $this->_em->getRepository('SuiteCRM\Core\Modules\Users\Entity\OAuthClient')
->findOneBy(['client_identifier' => $clientIdentifier]);
$user = $this->_em->getRepository('SuiteCRM\Core\Modules\Users\Entity\OAuthUser')
->findOneBy(['id' => $user_id]);
$client_id = $client->getId();
$token = OAuthAccessToken::fromArray(
[
'token' => $oauthToken,
'client_id' => $client_id,
'user_id' => $user_id,
'expires' => (new \DateTime())->setTimestamp($expires),
'scope' => $scope,
'user' => $user,
'client' => $client,
]
);
$this->_em->persist($token);
$this->_em->flush();
}
/**
* Delete a row
*
* @param string $token
* @return bool
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
*/
public function expireToken($token): bool
{
$token = $this->findOneBy(['token' => $token]);
if (!empty($token)) {
$ts = time();
$datetime = new \DateTime();
$datetime->setTimestamp($ts);
$token->setExpires($datetime);
$this->_em->merge($token);
return $this->_em->flush();
}
throw new \RuntimeException('No Token Found.');
}
}

View file

@ -1,82 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Storage;
use SuiteCRM\Core\Modules\Users\Entity\OAuthAuthorizationCode;
use Doctrine\ORM\EntityRepository;
use OAuth2\OpenID\Storage\AuthorizationCodeInterface;
class OAuthAuthorizationCodeStorage extends EntityRepository implements AuthorizationCodeInterface
{
/**
* @param $code
* @return object|null
*/
public function getAuthorizationCode($code)
{
$authCode = $this->findOneBy(['code' => $code]);
if ($authCode) {
$authCode = $authCode->toArray();
$authCode['expires'] = $authCode['expires']->getTimestamp();
}
return $authCode;
}
/**
* @param string $code
* @param mixed $client_id
* @param mixed $user_id
* @param string $redirect_uri
* @param int $expires
* @param null $scope
* @param null $id_token
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
*/
public function setAuthorizationCode(
$code,
$client_id,
$user_id,
$redirect_uri,
$expires,
$scope = null,
$id_token = null
) {
$client = $this->_em->getRepository('SuiteCRM\Core\Modules\Users\Entity\OAuthClient')
->findOneBy(['client_identifier' => $client_id]);
$user = $this->_em->getRepository('SuiteCRM\Core\Modules\Users\Entity\OAuthUser')
->findOneBy(['user_name' => $user_id]);
$authCode = OAuthAuthorizationCode::fromArray(
[
'code' => $code,
'client' => $client,
'user' => $user,
'redirect_uri' => $redirect_uri,
'expires' => (new \DateTime())->setTimestamp($expires),
'scope' => $scope,
'id_token' => $id_token
]
);
$this->_em->persist($authCode);
$this->_em->flush();
}
/**
* @param $code
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
*/
public function expireAuthorizationCode($code)
{
$authCode = $this->findOneBy(['code' => $code]);
$this->_em->remove($authCode);
$this->_em->flush();
}
}

View file

@ -1,102 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Storage;
use Doctrine\ORM\EntityRepository;
use OAuth2\Storage\ClientCredentialsInterface;
use SuiteCRM\Core\Modules\Users\Entity\OAuthClient;
class OAuthClientStorage extends EntityRepository implements ClientCredentialsInterface
{
/**
* Save function
*
* @param $client
* @return void
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
*/
public function save($client)
{
$clientEntity = $this->getEntity($client);
if (empty($clientEntity->getId())) {
$this->_em->persist($clientEntity);
} else {
$this->_em->merge($clientEntity);
}
$this->_em->flush();
}
/**
* @param $clientIdentifier
* @return array|object|null
*/
public function getClientDetails($clientIdentifier)
{
$client = $this->findOneBy(['client_identifier' => $clientIdentifier]);
if ($client) {
$client = $client->toArray();
}
return $client;
}
/**
* @param $clientIdentifier
* @param null $clientSecret
* @return bool
*/
public function checkClientCredentials($clientIdentifier, $clientSecret = null)
{
$client = $this->findOneBy(['client_identifier' => $clientIdentifier]);
if ($client) {
return $client->verifyClientSecret($clientSecret);
}
return false;
}
/**
* @param $clientId
* @param $grantType
* @return bool
*/
public function checkRestrictedGrantType($clientId, $grantType)
{
// we do not support different grant types per client in this example
return true;
}
/**
* @param $clientId
* @return bool
*/
public function isPublicClient($clientId)
{
return false;
}
/**
* @param $clientId
* @return null |null
*/
public function getClientScope($clientId)
{
return null;
}
/**
* Get Contact Entity
*
* @param array $entityData
* @return \Mvc\Entity\Contact
* @throws \Exception
*/
public function getEntity($entityData = []): \Mvc\Entity\Contact
{
return new OAuthClient($entityData);
}
}

View file

@ -1,33 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Storage;
use Doctrine\ORM\EntityRepository;
use OAuth2\Storage\PublicKeyInterface;
class OAuthPublicKeyStorage extends EntityRepository implements PublicKeyInterface
{
/**
* @param mixed $client_id
* @return mixed
*/
public function getPublicKey($client_id = null)
{
}
/**
* @param mixed $client_id
* @return mixed
*/
public function getPrivateKey($client_id = null)
{
}
/**
* @param mixed $client_id
* @return mixed
*/
public function getEncryptionAlgorithm($client_id = null)
{
}
}

View file

@ -1,104 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Storage;
use SuiteCRM\Core\Modules\Users\Entity\OAuthRefreshToken;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\ORMException;
use Doctrine\ORM\EntityRepository;
use OAuth2\Storage\RefreshTokenInterface;
class OAuthRefreshTokenStorage extends EntityRepository implements RefreshTokenInterface
{
/**
* @param $refreshToken
* @return object|null
*/
public function getRefreshToken($refreshToken)
{
$refreshToken = $this->findOneBy(['refresh_token' => $refreshToken]);
if ($refreshToken) {
$refreshToken = $refreshToken->toArray();
$refreshToken['expires'] = $refreshToken['expires']->getTimestamp();
}
return $refreshToken;
}
/**
* @param $refreshToken
* @param $clientIdentifier
* @param $user_id
* @param $expires
* @param null $scope
* @throws ORMException
* @throws OptimisticLockException
*/
public function setRefreshToken($refreshToken, $clientIdentifier, $user_id, $expires, $scope = null)
{
$client = $this->_em->getRepository('SuiteCRM\Core\Modules\Users\Entity\OAuthClient')
->findOneBy(['client_identifier' => $clientIdentifier]);
$client_id = $client->getId();
$user = $this->_em->getRepository('SuiteCRM\Core\Modules\Users\Entity\OAuthUser')
->findOneBy(['id' => $user_id]);
$refreshToken = OAuthRefreshToken::fromArray(
[
'refresh_token' => $refreshToken,
'client' => $client,
'user' => $user,
'expires' => (new \DateTime())->setTimestamp($expires),
'scope' => $scope,
'client_id' => $client_id,
'user_id' => $user_id,
]
);
$this->_em->persist($refreshToken);
$this->_em->flush();
}
/**
* @param $refreshToken
* @throws ORMException
* @throws OptimisticLockException
*/
public function unsetRefreshToken($refreshToken)
{
$refreshToken = $this->findOneBy(['refresh_token' => $refreshToken]);
$this->_em->remove($refreshToken);
$this->_em->flush();
}
/**
* Delete a row
*
* @param string $token
* @return bool
* @throws ORMException
* @throws OptimisticLockException
*/
public function expireToken($token): bool
{
$token = $this->findOneBy(['refresh_token' => $token]);
if (!empty($token)) {
$ts = time();
$datetime = new \DateTime();
$datetime->setTimestamp($ts);
$token->setExpires($datetime);
$this->_em->merge($token);
return $this->_em->flush();
}
throw new \RuntimeException('No Token Found.');
}
}

View file

@ -1,80 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Storage;
use Doctrine\ORM\EntityRepository;
use OAuth2\OpenID\Storage\UserClaimsInterface;
use SuiteCRM\Core\Modules\Users\Entity\OAuthUserClaims;
class OAuthUserClaimsStorage extends EntityRepository implements UserClaimsInterface
{
/**
* @param mixed $user_id
* @param string $scope
* @return array|bool
*/
public function getUserClaims($user_id, $scope)
{
if (!$userDetails = $this->getUserDetails($user_id)) {
return false;
}
$claims = explode(' ', trim($claims));
$userClaims = [];
// for each requested claim, if the user has the claim, set it in the response
$validClaims = explode(' ', self::VALID_CLAIMS);
foreach ($validClaims as $validClaim) {
if (in_array($validClaim, $claims, true)) {
if ($validClaim == 'address') {
// address is an object with subfields
$userClaims['address'] = $this->getUserClaim($validClaim, $userDetails['address'] ?: $userDetails);
} else {
$userClaims = array_merge($userClaims, $this->getUserClaim($validClaim, $userDetails));
}
}
}
return $userClaims;
}
/**
* @param $claim
* @param $userDetails
* @return array
*/
protected function getUserClaim($claim, $userDetails)
{
$userClaims = [];
$claimValuesString = constant(sprintf('self::%s_CLAIM_VALUES', strtoupper($claim)));
$claimValues = explode(' ', $claimValuesString);
foreach ($claimValues as $value) {
$userClaims[$value] = isset($userDetails[$value]) ? $userDetails[$value] : null;
}
return $userClaims;
}
/**
* @param $username
* @return array|bool
*/
public function getUserDetails($username)
{
if (!isset($this->userCredentials[$username])) {
return false;
}
return array_merge(
[
'user_id' => $username,
'password' => null,
'first_name' => null,
'last_name' => null,
],
$this->userCredentials[$username]
);
}
}

View file

@ -1,68 +0,0 @@
<?php
namespace SuiteCRM\Core\Modules\Users\Storage;
use Doctrine\ORM\EntityRepository;
use OAuth2\Storage\UserCredentialsInterface;
class OAuthUserStorage extends EntityRepository implements UserCredentialsInterface
{
/**
* @param $username
* @param $password
* @return bool
*/
public function checkUserCredentials($username, $password)
{
// $user = $this->findOneBy(['user_name' => $username]);
//
// if ($user) {
// return $user->verifyPassword($password);
// }
//
// return false;
return true;
}
/**
* @param $username
* @return object|null ARRAY the associated "user_id" and optional "scope" values
* ARRAY the associated "user_id" and optional "scope" values
* This function MUST return FALSE if the requested user does not exist or is
* invalid. "scope" is a space-separated list of restricted scopes.
* @code
* return array(
* "user_id" => USER_ID, // REQUIRED user_id to be stored with the authorization code or access token
* "scope" => SCOPE // OPTIONAL space-separated list of restricted scopes
* );
* @endcode
*/
public function getUserDetails($username)
{
$user = $this->findOneBy(['username' => $username]);
if ($user) {
$user = $user->toArray();
}
return $user;
}
// public function setSessionId($accesstoken, $session_id)
// {
// $tokenEntity = $this->_em->getRepository('SuiteCRM\Core\Modules\Users\Entity\oAuthAccessToken')
// ->findOneBy(['token' => $accesstoken]);
//
// $userId = $tokenEntity->getUserId();
//
// $userEntity = $this->_em->getRepository('SuiteCRM\Core\Modules\Users\Entity\oAuthUser')
// ->findOneBy(['id' => $userId]);
//
// $userEntity->setSessionId($session_id);
//
// $this->_em->merge($userEntity);
//
// $this->_em->flush();
// }
}

Some files were not shown because too many files have changed in this diff Show more