This is a plugin based on Vokuro ACL idea

Overview

IMPORATNT! You should switch to branch v3.0.0

We have switched to facebook/graph-sdk 5.4 !

$ composer require crada/phalcon-user-plugin:^3.0

Phalcon User Plugin (v 2.0)

About

This is a plugin based on Vokuro ACL idea.

Features

  • Login / Register with Facebook account
  • Login / Register with LinkedIn account
  • Login / Register with Twitter account
  • Login / Register with Google account
  • Change password
  • Password recovery by email
  • Protect different areas from your website, where a user must be logged in, in order to have access
  • Protect different actions, based on the ACL list for each user
  • User profile: birth date, birth location, current location, profile picture
  • Locations - save locations using google API - see Wiki for examples
  • Simple notifications system

Installation

The recommended installation is via Composer. Just add the following line to your composer.json:

{
    "require": {
        "crada/phalcon-user-plugin": "~2.0"
    }
}
$ php composer.phar update

Plug it

Add the following lines where to your events manager:

$security = new \Phalcon\UserPlugin\Plugin\Security($di);
$eventsManager->attach('dispatch', $security);

Full example code:

use Phalcon\UserPlugin\Plugin\Security as SecurityPlugin;
use Phalcon\Mvc\Dispatcher;

$di->setShared(
    'dispatcher',
    function() use ($di) {
        $eventsManager = $di->getShared('eventsManager');

        $security = new SecurityPlugin($di);
        $eventsManager->attach('dispatch', $security);

        $dispatcher = new Dispatcher();
        $dispatcher->setEventsManager($eventsManager);

        return $dispatcher;
    }
);

Register Auth, Mail and Acl services

use Phalcon\UserPlugin\Auth\Auth;
use Phalcon\UserPlugin\Acl\Acl;
use Phalcon\UserPlugin\Mail\Mail;

$di->setShared(
    'auth',
    function() {
        return new Auth();
    }
);

$di->setShared(
    'acl',
    function() {
        return new Acl();
    }
);

$di->setShared(
    'mail',
    function() {
        return new Mail();
    }
);

Configuration

You must add configuration keys to your config.php file. If you are using a multimodule application, i recommend you to set up the configuration separately for each module.

Configuration examples

In the example bellow, you will treat your website as public, EXCEPT the actions ACCOUNT and PROFILE from the USER controller:

'pup' => [
    'redirect' => [
        'success' => 'user/profile',
        'failure' => 'user/login'    
    ],
    'resources' => [
        'type' => 'public',
        'resources' => [
            '*' => [
                // All except
                'user' => ['account', 'profile']
            ]
        ]
    ]
];

In the example bellow, the ONLY PUBLIC resources are the actions LOGIN and REGISTER from the USER controller:

'pup' => [
    'redirect' => [
        'success' => 'user/profile',
        'failure' => 'user/login'    
    ],
    'resources' => [
        'type' => 'public',
        'resources' => [
            'user' => [
                'user' => ['login', 'register']
            ]
        ]
    ]
];

In the example bellow, you will treat your website as private, EXCEPT the actions LOGIN and REGISTER from the USER controller:

'pup' => [
    'redirect' => [
        'success' => 'user/profile',
        'failure' => 'user/login'    
    ],
    'resources' => [
        'type' => 'private',
        'resources' => [
            '*' => [
                // All except
                'user' => ['login', 'register']
            ]
        ]
    ]
];

In the example bellow, the ONLY PRIVATE resources are the actions ACCOUNT and PROFILE from the USER controller:

'pup' => [
    'redirect' => [
        'success' => 'user/profile',
        'failure' => 'user/login'    
    ],
    'resources' => [
        'type' => 'private',
        'resources' => [
            'user' => [
                'user' => ['account', 'profile']
            ]
        ]
    ]
];

Configuration example with connectors:

// phalcon-user-plugin
'pup' => [
    'redirect' => [
        'success' => 'user/profile',
        'failure' => 'user/login'    
    ],
    'resources' => [
        'type' => 'public',
        'resources' => [
            '*' => [
                // All except
                'user' => ['account', 'profile']
            ]
        ]
    ],
    'connectors' => [
        'facebook' => [
            'appId' => 'YOUR_FACEBOOK_APP_ID',
            'secret' => 'YOUR_FACEBOOK_APP_SECRET'
        ],
        'linkedIn' => [
            'api_key' => 'YOUR_LINKED_IN_APP_ID',
            'api_secret' => 'YOUR_LINKED_IN_APP_SECRET',
            'callback_url' => 'CALLBACK_URL'
        ],
        'twitter' => [
            'consumer_key' => 'TWITTER_CONSUMER_KEY',
            'consumer_secret' => 'TWITTER_CONSUMER_SECRET',
            // Leave empty if you don't want to set it
            'user_agent' => 'YOUR_APPLICATION_NAME'
        ],
        'google' => [
            'application_name' => 'YOUR_APPLICATION_NAME',
            'client_id' => 'YOUR_CLIENT_ID',
            'client_secret' => 'YOUR_CLIENT_SECRET',
            'developer_key' => 'YOUR_DEVELOPER_KEY',
            'redirect_uri' => 'YOUR_REDIRECT_URI'
        ]
    ]
];

Example controller

class UserController extends Controller
{
    /**
     * Login user
     * @return \Phalcon\Http\ResponseInterface
     */
    public function loginAction()
    {
        if (true === $this->auth->isUserSignedIn()) {
            $this->response->redirect(['action' => 'profile']);
        }

        $form = new LoginForm();

        try {
            $this->auth->login($form);
        } catch (AuthException $e) {
            $this->flash->error($e->getMessage());
        }

        $this->view->form = $form;
    }

    /**
     * Login with Facebook account
     */
    public function loginWithFacebookAction()
    {
        try {
            $this->view->disable();
            return $this->auth->loginWithFacebook();
        } catch(AuthException $e) {
            $this->flash->error('There was an error connectiong to Facebook.');
        }
    }

    /**
     * Login with LinkedIn account
     */
    public function loginWithLinkedInAction()
    {
        try {
            $this->view->disable();
            $this->auth->loginWithLinkedIn();
        } catch(AuthException $e) {
            $this->flash->error('There was an error connectiong to LinkedIn.');
        }
    }

    /**
     * Login with Twitter account
     */
    public function loginWithTwitterAction()
    {
        try {
            $this->view->disable();
            $this->auth->loginWithTwitter();
        } catch(AuthException $e) {
            $this->flash->error('There was an error connectiong to Twitter.');
        }
    }

    /**
     * Login with Google account
     */
    public function loginWithGoogleAction()
    {
        try {
            $this->view->disable();
            $this->auth->loginWithGoogle();
        } catch(AuthException $e) {
            $this->flash->error('There was an error connectiong to Google.');
        }
    }

    /**
     * Logout user and clear the data from session
     *
     * @return \Phalcon\Http\ResponseInterface
     */
    public function signoutAction()
    {
        $this->auth->remove();
        return $this->response->redirect('/', true);
    }
}

Known issues

  • Twitter does not provide us the email. We are generating a random email for the user. It is your choice how you handle this

Examples

TODO

  • Implement CRUD templates for ACl, UserManagement, etc
Comments
  • Blank pages

    Blank pages

    I am trying to use this plugin in a new project. However, once "configured", blank pages appear and nothing is displayed.

    1. Created blank project through DevTools (latest versions of everything)
    2. Downloaded PhalconUserPlugin through Composer.
    3. Configured services.php like in the Plugin README.md
    4. Copied resources array (PUBLIC version) from README.md to config.php
    5. Added path to PhalconUserPlugin to config:
    'UserPlugin'     => __DIR__ . '/../../vendor/crada/phalcon-user-plugin/Phalcon/UserPlugin/'
    
    1. registeredNamespaces for the Plugin:
    $loader->registerNamespaces(
        array(
            'Phalcon\UserPlugin' => $config->application->UserPlugin
        )
    )->register();
    
    1. SQL Schema imported to DB (and configured in config.php)
    2. Accessed to index: blank page appears.

    Am I missing some steps? Could you help me in getting this working?

    Thank you!

    opened by Miguel-Herrero 8
  • Example of full app/config.php please

    Example of full app/config.php please

    I'm trying to start the Plugin, but it won't work.

    Now i detect, you use the translate service, i don't use.

    So, can you give us a full example of all the required services and the config.php?

    Thanks :)

    PS: The Plugin is awsome!

    opened by okaufmann 3
  • Example of using ACL?

    Example of using ACL?

    Could someone please provide an example of protecting specific actions, based on the ACL list?

    It might also be a good idea to define the default GroupID in the config, instead of setting it to 2 for all new users.

    opened by mizterp 2
  • Composer requirements fail

    Composer requirements fail

    $ composer update
    

    Composer sais:

    Your requirements could not be resolved to an installable set of packages.
    
      Problem 1
        - crada/phalcon-user-plugin 1.x-dev requires nyholm/google-api-php-client dev-master -> satisfiable by nyholm/google-api-php-client[dev-master].
    

    It's also print the same problem about imagine package;

    When i force this packages from global project config like this:

        "require": {
          "nyholm/google-api-php-client":"dev-master",
          "imagine/imagine":"dev-master",
          "crada/phalcon-user-plugin": "@dev"
        }
    

    the installation goes ok, but composer sais:

    Package nyholm/google-api-php-client is abandoned, you should avoid using it. Use google/google-api-php-client instead.
    Package facebook/php-sdk is abandoned, you should avoid using it. Use facebook/php-sdk-v4 instead.
    

    Could u update those dependencies in your repo?

    opened by alexglue 2
  • noticed 2 little issues

    noticed 2 little issues

    hey hey, cool project - like it so far :).

    Noticed two little things, created two pull requests.

    two times variables were used inside functions that were not set before ( probably copy pasted but forgot to c/p the part to get it from $this->di )

    maybe syntax check to avoid these mistakes?

    opened by loeken 1
  • Why cann't this plugin on production?

    Why cann't this plugin on production?

    https://github.com/calinrada/PhalconUserPlugin#about

    I need a special config?, i can help for solve these issues/problems?, any idea?

    Explain me more please

    Grettings,

    opened by sairoko12 1
  • Why getConfigStructure is private?

    Why getConfigStructure is private?

    Why getConfigStructure is private? I want extend Security for multimodule variant, but cant - getConfigStructure is private.

    'moduleName1' =>[
    'resources' => [
                'type' => 'public',
                'resources' => [
                   ... ],
                ]
            ],
    ],
    'moduleName2' =>[
    'resources' => [
                'type' => 'public',
                'resources' => [
                   ... ],
                ]
            ],
    ],
    
    
    opened by mzf 1
  • Swift Mailer

    Swift Mailer

    i got error when i try to register new user , added user to database done successfully but when it's try to send confirmation email i got this error

    Fatal error: Class 'Swift_Message' not found in vendor\crada\phalcon-user-plugin\Phalcon\UserPlugin\Mail\Mail.php on line 89

    can you help me please

    opened by sniver 1
  • Fix for

    Fix for "Service 'config' wasn't found" error

    I was getting the following error:

    Service 'config' wasn't found in the dependency injection container
    

    To fix this I had to do add the following in the Services.php (where Services are globally registered):

    //added this "set"
    $di->set(
        'config',
        function () use ($config) {
            return $config;
        }
    );
    
    //Based on documentation, I only had this
    $di['dispatcher'] = function() use ($di) {
        $eventsManager = $di->getShared('eventsManager');
        $security = new \Phalcon\UserPlugin\Plugin\Security($di);
        $eventsManager->attach('dispatch', $security);
    
        $dispatcher = new Dispatcher();
        $dispatcher->setEventsManager($eventsManager);
        return $dispatcher;
    };
    
    opened by mizterp 1
  • Updates to accomodate testing

    Updates to accomodate testing

    Altered the directory structure to be able to add tests, the library now resides in lib/ and updated composer to reflect that (needs to be tested):

    "psr-4": { "Phalcon\\UserPlugin\\": "lib/" }
    

    A new directory tests/ has been created for unit tests and a test has been created for the security plugin.

    opened by oligus 1
  • Suggestions for schema fix

    Suggestions for schema fix

    Thanx for updated version!

    1. Could u plz to rename user table to users? All of your entities named in plural style but user table.
    2. It's much effective to remove user: banned, active, suspended columns and add column status;
    3. Rename user_email_confirmations.modified_at column to updated_at column (like in other cases).
    4. Fix foreign keys
    5. Remove profile_id column from user table
    6. Add postrges schema-variant

    See my https://gist.github.com/alexglue/f5241525e8ef882e1b17 for details

    opened by alexglue 1
  • $di as input in /Plugin/Security

    $di as input in /Plugin/Security

    Hello,

    I'm little confused about $security = new SecurityPlugin($di); in installation, there is no contructor in Security class, where did it came from ?

    opened by sarpaykent 0
  • Fatal exception when disabling view on null in Plugin/Security.php

    Fatal exception when disabling view on null in Plugin/Security.php

    Following docs and setting my app/config/services.php as follows:

    /**
     * Set dispatcher adding UserPlugin (crada/phalcon-user-plugin)
     */
    $di->setShared(
      'dispatcher',
      function () use ($di) {
        $eventsManager = $di->getShared('eventsManager');
        
        $security = new SecurityPlugin();
        $eventsManager->attach('dispatch', $security);
        
        $dispatcher = new Dispatcher();
        $dispatcher->setEventsManager($eventsManager);
        
        return $dispatcher;
      }
    );
    
    /**
     * Set auth service to UserPlugin/Auth (crada/phalcon-user-plugin)
     */
    $di->setShared(
      'auth',
        function () {
          return new Auth();
        }
    );
    
    /**
     * Set ACL service to UserPlugin/Acl (crada/phalcon-user-plugin)
     */
    $di->setShared(
      'acl',
        function () {
          return new Acl();
        }
    );
    
    /**
     * Set mail service to UserPlugin/Mail (crada/phalcon-user-plugin)
     */
    $di->setShared(
      'mail',
        function () {
          return new Mail();
        }
    );
    

    Results in exception:

    ( ! ) Fatal error: Uncaught Error: Call to a member function disable() on null in /var/www/project/vendor/crada/phalcon-user-plugin/lib/Plugin/Security.php on line 115
    --
    1 | 0.0000 | 399984 | {main}( ) | .../index.php:0
    2 | 0.0013 | 432208 | handle ( ) | .../index.php:42
    3 | 0.0015 | 453872 | dispatch ( ) | .../index.php:42
    4 | 0.0015 | 454336 | fire ( ) | .../index.php:42
    5 | 0.0015 | 455344 | fireQueue ( ) | .../index.php:42
    6 | 0.0015 | 455792 | Phalcon\UserPlugin\Plugin\Security->beforeDispatchLoop( ) | .../index.php:42
    

    Both the following changes in vendor/crada/phalcon-user-plugin/lib/Plugin/Security.php stopped the fatal error (not a solution, just targets error location):

    /**
         * beforeDispatchLoop.
         *
         * @param Event      $event
         * @param Dispatcher $dispatcher
         *
         * @return \Phalcon\Http\ResponseInterface
         */
        public function beforeDispatchLoop(Event $event, Dispatcher $dispatcher)
        {
            $auth = $this->getAuth($dispatcher);
            $view = $this->getView($dispatcher);
    
            // ...
    
            if (true === $needsIdentity) {
                if (!is_array($identity)) {
                    $this->flash->notice('Private area. Please login.');
    
                    //$this->view->disable(); // Commenting this out stops fatal error
    
                    return $this->response->redirect($config->pup->redirect->failure)->send();
                }
            }
    
            $view->setVar('identity', $identity);
        }
    

    I noticed Security::setView doesn't seem to be called anywhere, so tried changing $this->view->disable() to $view->disable():

    /**
         * beforeDispatchLoop.
         *
         * @param Event      $event
         * @param Dispatcher $dispatcher
         *
         * @return \Phalcon\Http\ResponseInterface
         */
        public function beforeDispatchLoop(Event $event, Dispatcher $dispatcher)
        {
            $auth = $this->getAuth($dispatcher);
            $view = $this->getView($dispatcher);
    
            // ...
    
            if (true === $needsIdentity) {
                if (!is_array($identity)) {
                    $this->flash->notice('Private area. Please login.');
    
                    $view->disable(); // Changing this to $view fixes fatal error
    
                    return $this->response->redirect($config->pup->redirect->failure)->send();
                }
            }
    
            $view->setVar('identity', $identity);
        }
    
    opened by ronindesign 1
  • The logic of checking 'PUBLIC' and 'EXCEPT' is right?

    The logic of checking 'PUBLIC' and 'EXCEPT' is right?

    I check the code of "Phalcon\UserPlugin\Plugin\Security.php". And I find the logic code of checking authority is not right. Below are code fragments:

    /**
     * Check for public resources.
     *
     * @param array  $resources
     * @param string $actionName
     * @param string $controllerName
     *
     * @return bool
     */
    private function checkPublicResources($resources, $actionName, $controllerName)
    {
        $resources = isset($resources['*']) ? $resources['*'] : $resources;
        foreach ($resources as $controller => $actions) {
            if ($controller == $controllerName) {
                if (isset($controller['*'])) {
                    return true;
                } else {
                    if (in_array($actionName, $actions) || $actions[0] == '*') {
                        return true;
                    }
                }
            }
        }
        return false;
    }
    

    Above logic code can not reach the goal which the doc say:

    In the exampe bellow, the ONLY PUBLIC resurces are the actions LOGIN and REGISTER from the USER controller:

    'pup' => array(
        'redirect' => array(
            'success' => 'user/profile',
            'failure' => 'user/login'
        ),
        'resources' => array(
            'type' => 'public',
            'resources' => array(
                'user' => array('login', 'register')
            )
        )
    )
    

    Think ! So sorry my bad english.

    opened by aisuhua 2
  • how to use it? Any demo?

    how to use it? Any demo?

    when I insert $di['dispatcher'] = function() use ($di) { $eventsManager = $di->getShared('eventsManager'); $security = new \Phalcon\UserPlugin\Plugin\Security($di); $eventsManager->attach('dispatch', $security);

            $dispatcher = new \Phalcon\Mvc\Dispatcher();
            $dispatcher->setEventsManager($eventsManager);
            return $dispatcher;
        };
    

    to my project, it's report fatal error: Call to a member function hasRememberMe() on a non-object. I need setAuth first? Could you uploads any demo how to use it? Thanks.

    opened by mikguo 9
  • [question] FailedLogins, SuccessLogins, ResetsPasswords...

    [question] FailedLogins, SuccessLogins, ResetsPasswords...

    Hi,

    wouldn't be nice if instead of database data with models we use Loggers in those actions? So instead of filling a table with rows we send a log somewhere, db, firephp, file, etc...

    opened by Surt 1
  • Imagine requirements trouble

    Imagine requirements trouble

    $ composer update
    Loading composer repositories with package information
    Updating dependencies (including require-dev)
    Your requirements could not be resolved to an installable set of packages.
    
      Problem 1
        - Installation request for crada/phalcon-user-plugin 2.0 -> satisfiable by crada/phalcon-user-plugin[2.0].
        - crada/phalcon-user-plugin 2.0 requires imagine/imagine dev-master -> no matching package found.
    

    The installation goes ok after:

        "require": {
          "imagine/imagine":"dev-master",
          "crada/phalcon-user-plugin": "2.0"
        }
    
    opened by alexglue 3
Owner
Calin Rada
Unicorn. (He/Him)
Calin Rada
GPT-3 powered business idea generator

The idea (lol) is to give you inspiration to make something cool, if you lack inspiration right now. Many ideas might not be perfect but they might give you the spark to start thinking to get to a really good idea further on.

levelsio 17 Feb 9, 2022
The tool converts different error reporting standards for deep compatibility with popular CI systems (TeamCity, IntelliJ IDEA, GitHub Actions, etc).

JBZoo / CI-Report-Converter Why? Installing Using as GitHub Action Example GitHub Action workflow Available Directions Help description in terminal Co

JBZoo Toolbox 17 Jun 16, 2022
A plugin manager for PocketMine-MP downloads plugin from PocketMine-MP official plugin repository

oh-my-pmmp A plugin manager for PocketMine-MP Getting Started Prerequisites Your server MUST RUN the latest version of PocketMine. Installation From P

thebigcrafter 6 Jan 4, 2023
Integrates the ClassicPress Plugin Directory and any plugin stored in GitHub (tagged with classicpress-plugin) in the ClassicPress Admin

ClassicPress Plugin Directory Adds a new screen in a ClassicPress Install where you can browse, install, activate, deactivate, update, delete and pagi

TukuToi 3 Dec 27, 2022
A text-based, persistent browser-based strategy game (PBBG) in a fantasy war setting

Note: OpenDominion is still in development. Some features of the game have not been implemented yet. Introduction OpenDominion is a free and open-sour

null 180 Dec 28, 2022
SPAM Registration Stopper is a Q2A plugin that prevents highly probable SPAM user registrations based on well-known SPAM checking services and other techniques

SPAM Registration Stopper [by Gabriel Zanetti] Description SPAM Registration Stopper is a Question2Answer plugin that prevents highly probable SPAM us

Gabriel Zanetti 2 Jan 23, 2022
Powerful land plugin, based on PMMP.

iLand Powerful land plugin, based on PMMP Features Land management with Form UI The border of the selected land Custom land settings Customize the per

David-pm-pl 9 Dec 6, 2022
A lightweight queue based on Redis Stream for webman plugin.

workbunny/webman-rqueue ?? A lightweight queue based on Redis Stream for webman plugin. ?? A lightweight queue based on Redis Stream for webman plugin

workbunny 10 Dec 12, 2022
Powerful land plugin, based on PMMP.

iLand Powerful land plugin, based on PMMP Features Land management with Form UI The border of the selected land Custom land settings Customize the per

Block Magic Dev 7 Jul 26, 2022
WordPress plugin renames image filenames to be more SEO friendly, based on the post's data and image metadata.

=== Automatic image Rename === Contributors: wpsunshine Tags: image, images, SEO, rename, optimization Requires at least: 5.0 Tested up to: 6.2.2 Stab

null 8 Jun 11, 2023
This Pocketmine-MP plugin is a plugin including a complete faction system.

SimpleFaction Simple faction plugin replacing FactionsPro which is no longer updated. Commands Command Name Command Description Available for /f help

Ayzrix 33 Dec 19, 2022
SpawnInLobby Pocketmine-MP plugin. With this plugin the player will always join the game at the default world spawn point

SpawnInLobby Pocketmine-MP plugin. With this plugin the player will always join the game at the default world spawn point

null 1 Jan 7, 2022
Ratio plugin is a luck plugin. The more lucky you are, the more you win!

Ratio Ratio plugin is a luck plugin. The more lucky you are, the more you win Features When you break a block (Cobblestone), it gives/puts you somethi

Ali Tura Çetin 2 Apr 25, 2022
actionMaster is a new faction plugin that aims at flexibility and customization of the plugin by the user and the developers.

FactionMaster is a new faction plugin that aims at flexibility and customization of the plugin by the user and the developers. It includes all the basic functionality of a faction plugin and data storage in MySQL or SQLITE. This is done by adding an extension system and a translation system. FactionMaster has a will of accessibility to the players and especially not to have to remember a lot of commands to play, all is done via interface.

FactionMaster 21 Dec 26, 2022
Api.video-wordpress-plugin - The official api.video plugin for WordPress

api.video WordPress Plugin api.video is the video infrastructure for product builders. Lightning fast video APIs for integrating, scaling, and managin

api.video 5 Oct 19, 2022
Ied plugin composer - Inspired Plugin Composer: Create, publish and edit plugins from within Textpattern CMS.

ied_plugin_composer Create, publish and edit plugins from within Textpattern CMS. Creates a new page under the Extensions tab where you can edit and e

Stef Dawson 8 Oct 3, 2020
BetterMobs - a plugin Remixed, by MadoxMC, the original plugin is maked by tgwaste

BetterMobsOverworld BetterMobs is a plugin Remixed, by MadoxMC, the original plugin is maked by tgwaste. MadoxMC Just Edited This plugin to Make 3 Compatible Plugins to add Mobs on your Overworld Worlds, NetherWorlds & EndWorlds, MadoxMC Idea.

MadoxMC 4 Dec 15, 2022
BetterMobs is a plugin Remixed, by MadoxMC, the original plugin is maked by tgwaste.

BetterMobs is a plugin Remixed, by MadoxMC, the original plugin is maked by tgwaste. MadoxMC Just Edited This plugin to Make 3 Compatible Plugins to add Mobs on your Overworld Worlds, NetherWorlds & EndWorlds, MadoxMC Idea.

MadoxMC 10 Dec 15, 2022
Opinionated version of Wikimedia composer-merge-plugin to work in pair with Bamarni composer-bin-plugin.

Composer Inheritance Plugin Opinionated version of Wikimedia composer-merge-plugin to work in pair with bamarni/composer-bin-plugin. Usage If you are

Théo FIDRY 25 Dec 2, 2022