Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
version: 2
defaults: &defaults
docker:
- image: circleci/python:2.7-stretch-browsers
- image: cimg/python:3.11.0-browsers
install_dependency: &install_dependency
name: Installation of build and deployment dependencies.
command: |
sudo apt install jq
sudo pip install awscli --upgrade
sudo pip install docker-compose
sudo apt update
sudo apt install python3-pip
sudo pip3 install awscli --upgrade
sudo pip3 install docker-compose
install_deploysuite: &install_deploysuite
name: Installation of install_deploysuite.
command: |
Expand Down Expand Up @@ -84,4 +86,4 @@ workflows:
context : org-global
filters:
branches:
only: master
only: master
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,24 @@ installation.These variables are mandatory.
- Run `docker-compose -f docker-compose.yml -f docker-compose.dev.yml up` to run Vanilla Forums
- The Vanilla Forums will be available at `http://<your_docker_machine_ip>` by default

## Local Deployment with local mysql
- Create `vanilla.env` and copy the contents of `sample.vanilla.env` into `vanilla.env`. Configure parameters.
- Create `mysql.env` and copy the contents of `sample.mysql.env` into `mysql.env`. Configure parameters.
`MYSQL_DATABASE` and `MYSQL_ROOT_PASSWORD` might be changed. You need to use these values during Vanilla Forums
installation.These variables are mandatory.
`MYSQL_ROOT_PASSWORD` specifies the password that will be set for the MySQL root superuser account.
- Make sure `MYSQL_HOST` is set to `mysql-local` in both `vanilla.env` and `mysql.env`
- Go to file `config/vanilla/config.php` and change the parameter `$Configuration['Garden']['Installed']` to `false` as shown below
```
$Configuration['Garden']['Installed'] = false;
```
- Run `docker-compose -f docker-compose.yml -f docker-compose.local.yml build --build-arg BRANCH=develop` to build the image
- Run `docker-compose -f docker-compose.yml -f docker-compose.local.yml up` to run Vanilla Forums
- After it is done, go to `localhost` in your browser
- You should be able to see the page similar to below
![Vanilla Forums Wizard](./docs/images/setup_wizard.png)
- Follow the instructions in [Setup Vanilla Forums](./docs/SetupVanillaForums.md) to complete installation.

## Docker Deployment with existing MySql
- You need to know how connect to MySQL Database:
- **Database Host**
Expand Down
5 changes: 5 additions & 0 deletions config/vanilla/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
// Trusted Domains. Specify one domain per line; use * for wildcard matches
$Configuration['Garden']['TrustedDomains'] = '*.topcoder-dev.com
*.topcoder.com';
$Configuration['Theme']['UniversalNavUrl'] = getenv('VANILLA_ENV') === 'prod'? '//uni-nav.topcoder.com/v1/tc-universal-nav.js':'//uni-nav.topcoder-dev.com/v1/tc-universal-nav.js';

$Configuration['Database']['Name'] = getenv('MYSQL_DATABASE');
$Configuration['Database']['Host'] = getenv('MYSQL_HOST');
Expand Down Expand Up @@ -117,6 +118,10 @@
$Configuration['Plugins']['Topcoder']['SSO']['TopcoderHS256']['Secret'] = getenv('TOPCODER_HS256_SECRET');
$Configuration['Plugins']['Topcoder']['SSO']['TopcoderRS256']['UsernameClaim'] = 'nickname';
$Configuration['Plugins']['Topcoder']['SSO']['TopcoderHS256']['UsernameClaim'] = 'handle';
$Configuration['Plugins']['Topcoder']['SSO']['TopcoderHS256']['UserIDClaim'] = getenv('VANILLA_ENV') == 'prod'? 'https://topcoder.com/userId' : 'https://topcoder-dev.com/userId';
$Configuration['Plugins']['Topcoder']['SSO']['TopcoderRS256']['UserIDClaim'] = getenv('VANILLA_ENV') == 'prod'? 'https://topcoder.com/userId' : 'https://topcoder-dev.com/userId';
$Configuration['Plugins']['Topcoder']['SSO']['TopcoderHS256']['PhotoUrlClaim'] = getenv('VANILLA_ENV') == 'prod'? 'picture' : 'picture';
$Configuration['Plugins']['Topcoder']['SSO']['TopcoderRS256']['PhotoUrlClaim'] = getenv('VANILLA_ENV') == 'prod'? 'picture' : 'picture';
$Configuration['Plugins']['Topcoder']['SSO']['RefreshTokenURL' ] = getenv('TOPCODER_PLUGIN_SSO_REFRESHTOKENURL');

// Filestack
Expand Down
35 changes: 18 additions & 17 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
version: '3'
services:
vanilla-forums:
image: vanilla-forums:latest
container_name: vanilla-forums
env_file:
- ./vanilla.env
build:
context: .
args:
- ENV
- VANILLA_VERSION=3.3
- CI_DEPLOY_TOKEN
- BRANCH
- TIDEWAYS_ENV
ports:
- 80:80
version: '3'
services:
vanilla-forums:
image: vanilla-forums:latest
container_name: vanilla-forums
env_file:
- ./vanilla.env
build:
context: .
args:
- ENV='dev'
- VANILLA_VERSION=3.3
- CI_DEPLOY_TOKEN
- BRANCH
- TIDEWAYS_ENV
ports:
- 80:80
- 443:443
217 changes: 217 additions & 0 deletions vanilla/library/core/class.smarty.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
<?php
/**
* Smart abstraction layer.
*
* @author Mark O'Sullivan <markm@vanillaforums.com>
* @copyright 2009-2019 Vanilla Forums Inc.
* @license GPL-2.0-only
* @package Core
* @since 2.0
*/

/**
* Vanilla implementation of Smarty templating engine.
*/
class Gdn_Smarty implements \Vanilla\Contracts\Web\LegacyViewHandlerInterface {

/** @var Smarty The smarty object used for the template. */
protected $_Smarty = null;

/**
*
*
* @param string $path
* @param Gdn_Controller $controller
*/
public function init($path, $controller) {
$smarty = $this->smarty();

// Get a friendly name for the controller.
$controllerName = get_class($controller);
if (stringEndsWith($controllerName, 'Controller', true)) {
$controllerName = substr($controllerName, 0, -10);
}

$smarty->assign('UniversalNavUrl', c('Theme.UniversalNavUrl'));
$smarty->assign('SignInUrl', signInUrl());
$smarty->assign('SignUpUrl', registerUrl('discussions'));
$smarty->assign('SignOutUrl', signOutUrl());

// Get an ID for the body.
$bodyIdentifier = strtolower($controller->ApplicationFolder.'_'.$controllerName.'_'.Gdn_Format::alphaNumeric(strtolower($controller->RequestMethod)));
$smarty->assign('BodyID', htmlspecialchars($bodyIdentifier));
//$Smarty->assign('Config', Gdn::config());

// Assign some information about the user.
$session = Gdn::session();
if ($session->isValid()) {
$user = [
'Name' => htmlspecialchars($session->User->Name),
'Photo' => '',
'CountNotifications' => (int)val('CountNotifications', $session->User, 0),
'CountUnreadConversations' => (int)val('CountUnreadConversations', $session->User, 0),
'SignedIn' => true,
'TopcoderPhotoUrl' => $session->getAttribute('TopcoderPhotoUrl', null),
'TopcoderUserID' => $session->getAttribute('TopcoderUserID', null)
];

$photo = $session->User->Photo;
if ($photo) {
if (!isUrl($photo)) {
$photo = Gdn_Upload::url(changeBasename($photo, 'n%s'));
}
} else {
$photo = UserModel::getDefaultAvatarUrl($session->User);
}
$user['Photo'] = $photo;
} else {
$user = false; /*array(
'Name' => '',
'CountNotifications' => 0,
'SignedIn' => FALSE);*/
}
$smarty->assign('User', $user);

// Make sure that any datasets use arrays instead of objects.
foreach ($controller->Data as $key => $value) {
if ($value instanceof Gdn_DataSet) {
$controller->Data[$key] = $value->resultArray();
} elseif ($value instanceof stdClass) {
$controller->Data[$key] = (array)$value;
}
}

$bodyClass = val('CssClass', $controller->Data, '', true);
$sections = Gdn_Theme::section(null, 'get');
if (is_array($sections)) {
foreach ($sections as $section) {
$bodyClass .= ' Section-'.$section;
}
}

$controller->Data['BodyClass'] = $bodyClass;

// Set the current locale for themes to take advantage of.
$locale = Gdn::locale()->Locale;
$currentLocale = [
'Key' => $locale,
'Lang' => str_replace('_', '-', Gdn::locale()->language(true)) // mirrors html5 lang attribute
];
if (class_exists('Locale')) {
$currentLocale['Language'] = Locale::getPrimaryLanguage($locale);
$currentLocale['Region'] = Locale::getRegion($locale);
$currentLocale['DisplayName'] = Locale::getDisplayName($locale, $locale);
$currentLocale['DisplayLanguage'] = Locale::getDisplayLanguage($locale, $locale);
$currentLocale['DisplayRegion'] = Locale::getDisplayRegion($locale, $locale);
}
$smarty->assign('CurrentLocale', $currentLocale);

$smarty->assign('Assets', (array)$controller->Assets);
// 2016-07-07 Linc: Request used to return blank for homepage.
// Now it returns defaultcontroller. This restores BC behavior.
$isHomepage = val('isHomepage', $controller->Data);
$path = ($isHomepage) ? "" : Gdn::request()->path();
$smarty->assign('Path', $path);
$smarty->assign('Homepage', $isHomepage); // true/false

// Assign the controller data last so the controllers override any default data.
$smarty->assign($controller->Data);

$security = new SmartySecurityVanilla($smarty);

$security->php_handling = Smarty::PHP_REMOVE;
$security->allow_constants = false;
$security->allow_super_globals = false;
$security->streams = null;

$security->setPhpFunctions(array_merge($security->php_functions, [
'array', // Yes, Smarty really blocks this.
'category',
'categoryUrl',
'checkPermission',
'commentUrl',
'discussionUrl',
'inSection',
'inCategory',
'ismobile',
'multiCheckPermission',
'getValue',
'setValue',
'url',
'useragenttype',
'userUrl',
]));

$security->php_modifiers = array_merge(
$security->php_functions,
['sprintf']
);

$smarty->enableSecurity($security);

}

/**
* Render the given view.
*
* @param string $path The path to the view's file.
* @param Controller $controller The controller that is rendering the view.
*/
public function render($path, $controller) {
$smarty = $this->smarty();
$this->init($path, $controller);
$compileID = $smarty->compile_id;
if (defined('CLIENT_NAME')) {
$compileID = CLIENT_NAME;
}

$smarty->setTemplateDir(dirname($path));
$smarty->display($path, null, $compileID);
}

/**
*
*
* @return Smarty The smarty object used for rendering.
*/
public function smarty() {
if (is_null($this->_Smarty)) {
$smarty = new SmartyBC();

$smarty->setCacheDir(PATH_CACHE.'/Smarty/cache');
$smarty->setCompileDir(PATH_CACHE.'/Smarty/compile');
$smarty->addPluginsDir(PATH_LIBRARY.'/SmartyPlugins');

// Gdn::pluginManager()->Trace = TRUE;
Gdn::pluginManager()->callEventHandlers($smarty, 'Gdn_Smarty', 'Init');

$this->_Smarty = $smarty;
}
return $this->_Smarty;
}

/**
* See if the provided template causes any errors.
*
* @param type $path Path of template file to test.
* @return boolean TRUE if template loads successfully.
*/
public function testTemplate($path) {
$smarty = $this->smarty();
$this->init($path, Gdn::controller());
$compileID = $smarty->compile_id;
if (defined('CLIENT_NAME')) {
$compileID = CLIENT_NAME;
}

$return = true;
try {
$result = $smarty->fetch($path, null, $compileID);
// echo wrap($Result, 'textarea', array('style' => 'width: 900px; height: 400px;'));
$return = ($result == '' || strpos($result, '<title>Fatal Error</title>') > 0 || strpos($result, '<h1>Something has gone wrong.</h1>') > 0) ? false : true;
} catch (Exception $ex) {
$return = false;
}
return $return;
}
}