doc has error? not sure - phalcon

http://docs.phalconphp.com/en/0.6.0/reference/odm.html
Setting multiple databases¶
In Phalcon, all models can belong to the same database connection or have an individual one. Actually, when Phalcon\Mvc\Collection needs to connect to the database it requests the “mongo” service in the application’s services container. You can overwrite this service setting it in the initialize method:
<?php
//This service returns a mongo database at 192.168.1.100
$di->set('mongo1', function() {
$mongo = new Mongo("mongodb://scott:nekhen#192.168.1.100");
return $mongo->selectDb("management");
});
//This service returns a mongo database at localhost
$di->set('mongo2', function() {
$mongo = new Mongo("mongodb://localhost");
return $mongo->selectDb("invoicing");
});
Then, in the Initialize method, we define the connection service for the model:
<?php
class Robots extends \Phalcon\Mvc\Collection
{
public function initialize()
{
$this->setConnectionService('management'); // here?
}
}

You are correct. The documentation was wrong. The correct usage is to set the appropriate service name (not the collection) using the setConnectionService.
http://docs.phalconphp.com/en/latest/reference/odm.html
<?php
// This service returns a mongo database at 192.168.1.100
$di->set(
'mongo1',
function()
{
$mongo = new Mongo("mongodb://scott:nekhen#192.168.1.100");
return $mongo->selectDb("management");
}
);
// This service returns a mongo database at localhost
$di->set(
'mongo2',
function()
{
$mongo = new Mongo("mongodb://localhost");
return $mongo->selectDb("invoicing");
}
);
Then, in the Initialize method, we define the connection service for the model:
.. code-block:: php
<?php
class Robots extends \Phalcon\Mvc\Collection
{
public function initialize()
{
$this->setConnectionService('mongo1');
}
}

Related

signalr avoid login repeat on load client side

I am using signalR pushnotification service.
I have created a partial view. Inside partial view. Here is my client side code:
<script type="text/javascript">
var objHub;
$(function () {
objHub = $.connection.AnilHub;
loadClientMethods(objHub);
$.connection.hub.start()
.done(function () { objHub.server.connect();
console.log('Now connected, connection ID=' + $.connection.hub.id); }
// at the same time i want to insert into database to set user is online.
objHub.server.login('user1');
)
.fail(function () { console.log('Could not Connect!'); });
function loadClientMethods(objHub) {
objHub.client.getMessages = function (message) {
$('#divMessage').append('<div><p>' + message + '</p></div>');
var height = $('#divMessage')[0].scrollHeight;
$('#divMessage').scrollTop(height);
}
}
</script>
Hub Code
[HubName("MyHub")]
public class MainHub : Hub
{
public void Connect()
{
try
{
string userGroup = "test";
var id = Context.ConnectionId;
Groups.Add(id, userGroup);
Clients.Caller.onConnected(id, userGroup);
}
catch
{
Clients.Caller.NoExistAdmin();
}
}
public void NotifyAllClients(string Message)
{
Clients.Group("test").getMessages(Message);
}
public override Task OnConnected()
{
// Set status online on database
return base.OnConnected();
}
public override Task OnDisconnected(bool stopCalled = false)
{
// set status disconnct in database
return base.OnDisconnected(stopCalled);
}
}
}
Now I just want to avoid re-loading check of login. because everytime I refresh the page it will call the connect method and call the hub method. How to avoid the re-connect issue. How Do I persist the things, even hub is not handle sessions.
Please suggest...
inside your html, in first load, create a random id and store it in cookies.
In your hub code, create an arraylist and store these random ids with corresponding connection ID.
In your html, try to read the random id from the cookies during each page refresh, if it is not found, it's a new connection, if it is found, use the old random id with a new connection ID to connect to your hub. Then in your hub arraylist, for this particular random id, replace the old connection ID with the new connection ID.

Access memcached object in model (Phalcon)

Following this document, I'm trying to retrieve memcached key within find() method in a model (in order to get cache version of the model&relations).
Does somebody know how should i access the memcached object which i set at the DI?
class Tags extends Phalcon\Mvc\Model {
protected function _getCache($key)
{
// how do i retreive memcached object?
}
protected static function _setCache($key)
{
// stores data in the cache
}
these are the settings as they are in DI:
$di->set('modelsCache', function()
{
//Cache data for one day by default
$frontCache = new \Phalcon\Cache\Frontend\Data(array(
"lifetime" => 86400
));
//Memcached connection settings
$cache = new \Phalcon\Cache\Backend\Memcache($frontCache, array(
"host" => "localhost",
"port" => "11211"
));
return $cache;
});
First, if it's a reusable "service", use getShared() / setShared() on the DI, otherwise you will end up creating a new instance every time you access it.
To actually retrieve it from anywhere in your app:
class Tags extends Phalcon\Mvc\Model {
protected function _getCache($key)
{
// how do i retreive memcached object?
$modelsChache = $this->di->getShared('modelsCache');
// Or if DI is not set on the model, though in 99.9% it will be unless you are doing something unusual.
$modelsChache = DI::getDefault()->getShared('modelsCache');
}
protected static function _setCache($key)
{
// stores data in the cache
// Same as above…
}

how to use SimpleSAMLphp in yii framework?

I have two project in yii framework and I want to use both project using SimpleSAMLphp with SSO. The condition, I need is if I login from the first project, i want access to the second project.
Thank you in advance.
First you load the SAML library by temporarily disabling the Yii autoloader. This is just to let you use the SAML classes and methods:
<?php
class YiiSAML extends CComponent {
private $_yiiSAML = null;
static private function pre() {
require_once (Yii::app()->params['simpleSAML'] . '/lib/_autoload.php');
// temporary disable Yii autoloader
spl_autoload_unregister(array(
'YiiBase',
'autoload'
));
}
static private function post() {
// enable Yii autoloader
spl_autoload_register(array(
'YiiBase',
'autoload'
));
}
public function __construct() {
self::pre();
//We select our authentication source:
$this->_yiiSAML = new SimpleSAML_Auth_Simple(Yii::app()->params['authSource']);
self::post();
}
static public function loggedOut($param, $stage) {
self::pre();
$state = SimpleSAML_Auth_State::loadState($param, $stage);
self::post();
if (isset($state['saml:sp:LogoutStatus'])) {
$ls = $state['saml:sp:LogoutStatus']; /* Only for SAML SP */
} else return true;
return $ls['Code'] === 'urn:oasis:names:tc:SAML:2.0:status:Success' && !isset($ls['SubCode']);
}
public function __call($method, $args) {
$params = (is_array($args) and !empty($args)) ? $args[0] : $args;
if (method_exists($this->_yiiSAML, $method)) return $this->_yiiSAML->$method($params);
else throw new YiiSAMLException(Yii::t('app', 'The method {method} does not exist in the SAML class', array(
'{method}' => $method
)));
}
}
class YiiSAMLException extends CException {
}
Then you define a filter extending the CFilter Yii class:
<?php
Yii::import('lib.YiiSAML');
class SAMLControl extends CFilter {
protected function preFilter($filterChain) {
$msg = Yii::t('yii', 'You are not authorized to perform this action.');
$saml = new YiiSAML();
if (Yii::app()->user->isGuest) {
Yii::app()->user->loginRequired();
return false;
} else {
$saml_attributes = $saml->getAttributes();
if (!$saml->isAuthenticated() or Yii::app()->user->id != $saml_attributes['User.id'][0]) {
Yii::app()->user->logout();
Yii::app()->user->loginRequired();
return false;
}
return true;
}
}
}
And finally, in the controllers you are interested to restrict, you override the filters() method:
public function filters() {
return array(
array(
'lib.SAMLControl'
) , // perform access control for CRUD operations
...
);
}
Hope it helps.
It can be done simply using "vendors" directory.
Download PHP Library from https://simplesamlphp.org/
Implement it in Yii Framework as a vendor library. (http://www.yiiframework.com/doc/guide/1.1/en/extension.integration)
Good Luck :)
I came across an Yii Extension for SimpleSAMLphp in github
https://github.com/asasmoyo/yii-simplesamlphp
You can load the simplesamlphp as a vendor library and then specify the autoload file in the extension.
Apart from the extension you can copy all the necessary configs and metadatas into the application and configure SimpleSAML Configuration to load the configurations from your directory, so you can keep the vendor package untouched for future updates.

Symfony authenticate user with external api key

I am trying to authenticate a user via external api key request following this http://symfony.com/doc/current/cookbook/security/api_key_authentication.html#cookbook-security-api-key-config
What is ["#your_api_key_user_provider"] ?
If I put something like ["test"] I get an error.
[UPDATE]
This is my ApiKeyAuthenticator.php:
// src/Acme/HelloBundle/Security/ApiKeyAuthenticator.php
namespace Acme\HelloBundle\Security;
use ////
class ApiKeyAuthenticator implements SimplePreAuthenticatorInterface
{
protected $userProvider;
public function __construct(ApiKeyUserProvider $userProvider)
{
$this->userProvider = $userProvider;
}
public function createToken(Request $request, $providerKey)
{
if (!$request->query->has('apikey')) {
throw new BadCredentialsException('No API key found');
}
return new PreAuthenticatedToken(
'anon.',
$request->query->get('apikey'),
$providerKey
);
}
public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
{
$apiKey = $token->getCredentials();
$username = $this->userProvider->getUsernameForApiKey($apiKey);
if (!$username) {
throw new AuthenticationException(
sprintf('API Key "%s" does not exist.', $apiKey)
);
}
$user = $this->userProvider->loadUserByUsername($username);
return new PreAuthenticatedToken(
$user,
$apiKey,
$providerKey,
$user->getRoles()
);
}
public function supportsToken(TokenInterface $token, $providerKey)
{
return $token instanceof PreAuthenticatedToken && $token->getProviderKey() === $providerKey;
}
}
While the user provider is this:
// src/Acme/HelloBundle/Security/ApiKeyUserProvider.php
namespace Acme\HelloBundle\Security;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
class ApiKeyUserProvider implements UserProviderInterface
{
public function getUsernameForApiKey($apiKey)
{
// Look up the username based on the token in the database, via
// an API call, or do something entirely different
$username = ...;
return $username;
}
public function loadUserByUsername($username)
{
return new User(
$username,
null,
// the roles for the user - you may choose to determine
// these dynamically somehow based on the user
array('ROLE_USER')
);
}
public function refreshUser(UserInterface $user)
{
// this is used for storing authentication in the session
// but in this example, the token is sent in each request,
// so authentication can be stateless. Throwing this exception
// is proper to make things stateless
throw new UnsupportedUserException();
}
public function supportsClass($class)
{
return 'Symfony\Component\Security\Core\User\User' === $class;
}
}
The service should be just this:
services:
# ...
apikey_authenticator:
class: Acme\SeedBundle\Security\ApiKeyAuthenticator
arguments: ["#ApiKeyUserProvider"]
But i got this error: The service "apikey_authenticator" has a dependency on a non-existent service "apikeyuserprovider".
Thanks
That is the user provider service that you should have created following this doc:
http://symfony.com/doc/current/cookbook/security/custom_provider.html
So you register your user provider as a service IE: apikey_userprovider
http://symfony.com/doc/current/cookbook/security/custom_provider.html#create-a-service-for-the-user-provider
Then pass it using ["#apikey_userprovider"]
So your Services File should look like:
parameters:
apikey_userprovider.class: Acme\HelloBundle\Security\ApiKeyUserProvider
apikey_authenticator.class: Acme\SeedBundle\Security\ApiKeyAuthenticator
services:
apikey_userprovider:
class: %apikey_userprovider.class%
apikey_authenticator:
class: %apikey_authenticator.class%
arguments: ["#apikey_userprovider"]
You need to define your user provider as a service. This is what the # operator is telling symfony to look for. Defining your classes in the parameters is just part of Symfony Coding Standards

Access doctrine from authentication failure handler in Symfony2

I'm trying to write some loggin failure info in database from a custom authentication handler.
My problem is to gain access to the database since I don't know where the Doctrine object might be stored
Here's my code for now :
namespace MyApp\FrontBundle\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request as Request;
use Symfony\Component\HttpFoundation\RedirectResponse as RedirectResponse;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\Security\Http\Authentication as Auth;
use Symfony\Component\Security\Core\Exception\AuthenticationException as AuthException;
class SecurityHandler implements Auth\AuthenticationFailureHandlerInterface
{
public function onAuthenticationFailure(Request $request, AuthException $token)
{
try
{
$lastLoginFailure = new DateTime();
// get database object here
}
catch(\Exception $ex)
{
}
}
}
Any ideas ?
Turn your SecurityHandler into a service and then inject the doctrine entity manager into it.
http://symfony.com/doc/current/book/service_container.html
Start command php app/console container:debug.
Copy doctrine.orm.entity_manager and paste to your hadler constructor arguments like
[...., #doctrine.orm.entity_manager].
In hadler use Doctrine\ORM\EntityManager;
I think you should extends your class "SecurityHandler" with ContainerAware if you want to use service since your Security Handler is not a controller.
class SecurityHandler extend ContainerAware implements Auth\AuthenticationFailureHandlerInterface{
public function onAuthenticationFailure(Request $request, AuthException $token)
{
try
{
$lastLoginFailure = new DateTime();
// get database object here
$doctrine = $this->container->get('doctrine');
$repository = $doctrine->getRepository('*NAME OF REPO*');
}
catch(\Exception $ex)
{
}
}
}