How to get the current Mongoid session or database - mongoid

I have a multitenant app and I use Mongoid.override_session(current_user.customer_id) to point to the appropriate customer database. I'm using paperclip to save photos to an S3 bucket and I'd like the folder structure to start with the customer_id but I can't find a way to get the current session or database from Mongoid. I found this question but the answers are not working for me on Mongoid v4.0.1. current_user is out of scope in the model code that sets up the URL for paperclip as is the paperclip initializer.

In case it helps someone else, here is a method I found that you can run on the class or an instance of your model
mongo_session.options[:database]
I added the following to my paperclip initializer;
#myapp/config/initializer/paperclip.rb
Paperclip.interpolates :customer_id do |attachment, style|
attachment.instance.mongo_session.options[:database]
end
Then you can reference :customer_id in your model
has_mongoid_attached_file :image,
:storage => :s3,
:s3_credentials => File.join(Rails.root, 'config', 'aws.yml'),
:styles => {
:medium => '600x600>',
:small => '300x300>',
:thumb => '100x100>'
},
:path => ':customer_id/:style/:filename',
:url => '/:customer_id/:style/:filename'

Related

CakePHP 3.5 Auth use multiple tables

I have an Auth process which works fine with one userModel. But not only because of my DB schema I need to have one login method/action which works with multiple models.
So far I've tried everything I was able to think of or find online - for example editing this Cake 1.3 solution into Cake 3 and a few more hints I was able to find.
However, I'm not able to figure it out.
Thank you for any answer.
My AppController component load:
$this->loadComponent('ExtendedAuth', [
'authenticate' => [
'Form' => [
//'userModel' => 'Admins',
'fields' => [
'username' => 'email',
'password' => 'password'
]
]
],
'loginAction' => [
'controller' => 'Admins',
'action' => 'login'
],
// If unauthorized, return them to page they were just on
'unauthorizedRedirect' => $this->referer(),
]);
My ExtendedAuthComponent:
class ExtendedAuthComponent extends AuthComponent
{
function identify($user = null, $conditions = null) {
$models = array('Admins', 'Users');
foreach ($models as $model) {
//$this->userModel = $model; // switch model
parent::setConfig('authenticate', [
AuthComponent::ALL => [
'userModel' => $model
]
]);
$result = parent::identify(); // let cake do its thing
if ($result) {
return $result; // login success
}
}
return null; // login failure
}
}
EDIT1: Description of situation
I have two separate tables (Admins, Users). I need just one login action which tries to use Admins table prior to Users. Because of the application logic I can't combine them to one table with something like 'is_admin' flag. So basically what I need is instead of one specific userModel set in Auth config, I need a set of models. Sounds simple and yet I'm not able to achieve it.
EDIT2: Chosen solution
Based on the answer below, I decided to update my schema. Auth users table is just simplified table with login credentials and role and other role-specific fields are then in separate tables which are used as a connection for other role-specific tables. Even though the answer is not exactly a solution for the asked question, it made me think more about any possible changes of the schema and I found this solution because of it so I'm marking it as a solution. I appreciate all comments as well.
As Mark already said in a comment: Don't use two users tables. Add a type field or role or whatever else and associated data in separate tables if it's different like admin_profiles and user_profiles.
Don't extend the Auth component. I wouldn't recommend to use it anymore any way because it's going to get deprecated in the upcoming 3.7 / 4.0 release. Use the new official authentication and authorization plugins instead.
If you insist on the rocky path and want to make your life harder, well go for it but then you should still not extend the auth component but instead write a custom authentication adapter. This is the right place to implement your custom 2-table-weirdness. Read this section of the manual on how to do it.

TYPO3 saving Backend content in another database

I want to store content from my Backend in another database.
So let's say i have this in my Backend:
How can i save the value (e.g. the float value in the picture) in another database?
The reason why i need this, is, because i have another database, which is being used for some dynamic content loaded onto my Website with PHP.
Hopefully, someone has an idea and can help me :)
I would use either a hook which updates the foreign database with the value which is triggered if something is changed in the TYPO3 backend or I would use a scheduler task / command controller which is triggered by CLI and runs all x minutes and changes the values in the database.
There are several ways to achieve that. I just assume that you want to create relations between the tt_content table of TYPO3 and some external table in a different database or even different storage engine (web-service, file-system, ...).
In that case you could extend the TCA of the tt_content table by an additional property, let's call it external_reference. The backend form then should provide an additional selector field that allows to chose entities of the external data-source.
The following example assumes that your extension key is called my_extension, this has to be adjusted of course to the actual naming.
You can do so by putting the following configuration to your extension in the folder typo3conf/ext/my_extension/Configuration/TCA/Overrides/tt_content.php:
<?php
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns(
'tt_content',
[
'external_reference' => [
'exclude' => 1,
'label' => 'External Source',
'config' => [
'type' => 'select',
'items' => [
['-- none --', 0]
],
'itemsProcFunc' => ExternalReferenceSelection::class . '->render',
'default' => 0,
]
],
]
);
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes(
'tt_content',
'external_reference'
);
Then you have to implement the selector and the retrieval from the external source, like e.g.
<?php
class ExternalReferenceSelection
{
public function render(array $parameters)
{
$references = ExternalReferenceRepository::instance()->findAll();
foreach ($references as $reference) {
$parameters['items'][] = [
$reference->getTitle(),
$reference->getIdentifier()
];
}
}
}
To be able to persist the selected reference, you have to extend the SQL schema of tt_content as well in typo3conf/ext/my_extension/ext_tables.sql
#
# Table structure for table 'tt_content'
#
CREATE TABLE tt_content (
external_reference int(11) unsigned DEFAULT '0' NOT NULL
);
The database schema is updated by invoking the database analyzer in the TYPO3 Install Tool, or by (re-)installing the extension in the Extension Manager.

Mocking a function using Laravel and PHPUnit

I am using Laravel for some projects, and I am trying to create a test for a function. Here is the function in the my controller:
public function showThoseThings()
{
return parent::httpRequest(
function ($context) {
$context->results['item'] = $this->object->findOrFail(list_id)->getElements;
}
);
}
the "getElements()" function is defined in the model as follow:
public function getElements()
{
return $this->belongsToMany(
'things',
'thing_to_list',
'list_id',
'thing_id'
)
->withPivot('position')
->orderBy('thing_to_list.position');
}
Basically in the backend there are three tables a list table that is a collection of things, then there is a things table that contains multiple things associated to a list then we have the pivot table. How can I mock this with Laravel. Here is what I have been doing:
public function testShowThoseTHingsSuccess()
{
$this->mock->shouldReceive('findOrFail')->with(1)->andReturn($this->mock);
$this->mock->shouldReceive('getElements')->once()->andReturn($this->mock);
$response = $this->call('GET', 'workingURI');
var_dump($response);
$this->assertTrue($response->isOk());
But when running phpunit in the command line I am getting:
"Unknown Error","message":"SQLSTATE[HY000] [1045] Access denied for user... Fails asserting that false is true".
I don't know what your $this->mock->.. method is doing but apparently not mocking the model you want.
Because the error states that something tries to access the database and doesn't have correct credentials.
Also the lines:
$this->mock->shouldReceive('findOrFail')->with(1)->andReturn($this->mock);
$this->mock->shouldReceive('getElements')->once()->andReturn($this->mock);
Makes no sense to me, You create a mock of a model and when the methods findOrFail or getElements are triggered you return the same object.. The method getElements states to me that there should be returned some array with models..
Some more info when you want to use a testing database
When you run unit test with laravel and uses the base test class, then Laravel sets the environment to testing. Make sure that you have the right database configuration set for this environment.
You can use I.E. the following configuration to create a database in memory for testing:
// app/config/testing/database.php
<?php
return array(
'default' => 'sqlite',
'connections' => array(
'sqlite' => array(
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => ''
),
)
);
Don't forget to migrate your DB schema before testing, place the following line in the public function setUp() of the base test class.
Artisan::call('migrate');
More info about simulating the databse: NetTuts testing laravel models

CakePHP virtualField find all not null

I have a database table "transactions" which has a field "account". I want to retrieve a subset of all not-null account rows from the current set of data and have it as a virtualField I can access down the line in my view.
class Transaction extends AppModel {
public $virtualFields = array(
"Accounts" => $this->Transaction->find("all", array("conditions" => array("not" => array("Transaction.account" => null))))
);
}
So that I get an array of all transactions with non-null account fields named "Accounts".
This doesn't work - gives me "unexpected T_VARIABLE" error (doesn't like $this). I was trying to follow the guide here. I'm a moderate level PHP developer and this is my first real Cake project, so I may be going about this completely wrong.
When you're inside the model that you're querying, you don't specify the model name, just:
$this->find('all'); // when you're inside transaction model
...so try this:
"Accounts" => $this->find("all", array("conditions" => array("not" => array("Transaction.account" => null))))

How do I get zend to recognize the paths to Propel ORM

I am trying to get Propel to work in my Zend app, it seems that I can get the Propel library to load (from library/propel) but when called I get the exception: 'No connection information in your runtime configuration file for datasource [default]' (when I try to make a connection: 'Propel::getConnection'). My Db is not even named 'default'. I have this in my bootstrap.php from another SO question/answer:
require_once 'propel/Propel.php';
Propel::setConfiguration($this->getOptions('propel/MyPropel-conf.php'));
Propel::initialize();
// so we can get the connection from the registry easily
return Propel::getConnection();
I want the Propel configs (classmap conf as well) to be in the '/application/configs' (copies are there too right now), but I thought If I can get Propel to load from library/propel, then maybe moving my 'conf' files there, I may get them to load too. It seems that if I 'force' the config, by manually loading the params, or if I seem to get it in a temporary 'right' location (or use an absolute path), the exception I then get is this:
'Unable to open PDO connection [wrapped: SQLSTATE[28000] [1045] Access denied for user 'www-data'#'localhost'
As if Propel is not paying any attention to my configs.
My config looks like this; converted from the xml:
$conf = array (
'datasources' =>
array (
'unmActTestDB' =>
array (
'adapter' => 'mysql',
'connection' =>
array (
'dsn' => 'mysql://root:PASSWORD#localhost/unmActTestDB',
),
),
'default' => 'unmActTestDB',
),
'log' =>
array (
'ident' => 'propel-act',
'level' => '7',
),
'generator_version' => '1.5.6',
);
$conf['classmap'] = include(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'classmap-unmActTestDB-conf.php');
return $conf;
If it helps, I still have the Zend PDO DB adapter loading in the application.ini file too, would that cause a clash?. Is there a standard way to get Propel to work with Zend? Or can anyone see what I'm doing wrong?
I have been to several posts here on SO, and a couple popular posts like this one The Adventures Of Merging Propel With Zend Framework and this one at Zend's dev zone Integrating Propel with the Zend Framework, among others including the Propel Docs. They have been helpful, but I am really struggling with this. Thanks in advance! My current Zend Directory structure looks like this (w/ the two propel confs also in the library/propel folder:
What I ended up doing is this:
I got a good grip on how to generate my models from a 'reverse' using Propel. It created (as before) a 'schema.xml' file for me to build my models with.
Also my 'runtime.xml' file was incorrect for my needs, after the build I was not connecting to the right database because of my omission of a few tags, overall it is quite simple though:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<log>
<ident>unmActTestDB</ident>
<level>7</level>
</log>
<propel>
<datasources default="unmActTestDB">
<datasource id="unmActTestDB">
<adapter>mysql</adapter>
<connection>
<dsn>mysql:host=localhost;dbname=unmActTestDB</dsn>
<user>zend</user>
<password>PASSWORD</password>
<database>unmActTestDB</database>
</connection>
</datasource>
</datasources>
</propel>
</config>
The 'dsn' tag has to be in the format above with the addition of the 'user', 'password', and the 'database' tags. This fixed my issue with the database connection errors. As quoted above (and here) the exception thrown was: 'No connection information in your runtime configuration file for datasource [default]'
As far as the loading of my models goes, I ended up putting them in my 'library' folder, I already have that folder autoloading in my app, plus it seemed like a good place form them.
here is an image of my 'updated' directory structure:
Note the addition of the 'unmActTestDB' folder in my directory, this is my ORM models.
Another thing to note is that I put my generated 'conf' files into my 'application/configs' folder. These are correct now, after the correction of the runtime.xml file and a 'rebuild'.
As a side note, I had to edit my 'schema.xml' file by hand (several times :) )...The original database used plural names for the tables, so I edited all the 'phpname' declarations (attributes actually, on the declaration tag) to be singular so I wouldn't access an object called 'Users'...instead I can now access a 'User' object. I kept the table names the same (tables are plural, and I won't have any issues importing the existing data, etc.) This was suggested by an answer to another one of my questions, see here How to get related object Propel ORM.
The other big edit I made was to add primary key declarations (again, attributes) for the many SQL views in the DB, also I added a 'readonly' and a 'noSQL' attributes to the declarations, this way I will have access (through the Propel models) to my views.
And, just to be thorough, and for those who are interested here is the addition to my 'bootstrap.php' file that does my 'Propel Init' for me...
protected function _initPropel()
{
$this->_logger->info('Bootstrap ' . __METHOD__);
require '../library/propel/Propel.php';
Propel::init(APPLICATION_PATH . '/configs/unmActTestDB-conf.php');
Propel::initialize();
return Propel::getConnection();
}
Another NOTE: the '$this->_logger->info('Bootstrap ' . METHOD);' calls my 'logging' method that just tells 'firePHP' that this method has loaded. The /configs/unmActTestDB-conf.php' calls the second 'conf' file that Propel generates... and here is the 'corrected' version of that file (the unmActTestDB.conf file that is), Note the changes in the 'connection' array.
<?php
// This file generated by Propel 1.5.6 convert-conf target
// from XML runtime conf file runtime-conf.xml
$conf = array (
'datasources' =>
array (
'unmActTestDB' =>
array (
'adapter' => 'mysql',
'connection' =>
array (
'dsn' => 'mysql:host=localhost;dbname=unmActTestDB',
'user' => 'zend',
'password' => 'PASSWORD',
'database' => 'unmActTestDB',
),
),
'default' => 'unmActTestDB',
),
'log' =>
array (
'ident' => 'unmActTestDB',
'level' => '7',
),
'generator_version' => '1.5.6',
);
$conf['classmap'] = include(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'classmap-unmActTestDB-conf.php');
return $conf;
I am off and running now! This was a great way to go, otherwise I was looking and writing sooo many mapping classes for my app. Propel (currently) generates over 300 models for this application! Plus the base classes, it would take me forever...

Resources