diff --git a/.gitignore b/.gitignore index c3b3785d1..f1ec7f109 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,6 @@ phpunit.phar tests/_app/config/db.local.php tests/_support/_generated tests/_output/* + +# composer lock file +composer.lock diff --git a/.travis.yml b/.travis.yml index f06155367..4d6b4eccd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,14 @@ language: php php: + - 7.1 - 7.0 - 5.6 - - 5.5 - - 5.4 +services: + - mysql # environment variable used in test suite -env: TEST_ENVIRONMENT=travis +env: TEST_ENVIRONMENT=travis MYSQL_HOST=localhost MYSQL_USER=root MYSQL_PASSWORD="" MYSQL_DATABASE="dektrium_test" # faster builds on new travis setup not using sudo sudo: false @@ -21,13 +22,12 @@ cache: # install dependencies install: - travis_retry composer self-update - - travis_retry composer global require "codeception/codeception:2.2.5" - travis_retry composer global require "fxp/composer-asset-plugin:~1.1.0" - travis_retry composer install --prefer-dist before_script: - mysql -e 'create database dektrium_test;' - php tests/_app/yii.php migrate --migrationPath=@dektrium/user/migrations --interactive=0 - - ~/.composer/vendor/bin/codecept build + - vendor/bin/codecept build -script: ~/.composer/vendor/bin/codecept run +script: vendor/bin/codecept run diff --git a/Module.php b/Module.php index d325ee8ce..e81d30abb 100644 --- a/Module.php +++ b/Module.php @@ -107,4 +107,11 @@ class Module extends BaseModule 'recover//' => 'recovery/reset', 'settings/' => 'settings/' ]; + + /** @var string The database connection to use for models in this module. */ + public $dbConnection = 'db'; + + public function getDb() { + return \Yii::$app->get($this->dbConnection); + } } diff --git a/README.md b/README.md index bc7765cb6..b26b914ab 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Yii2-user [![Build Status](https://img.shields.io/travis/dektrium/yii2-user/master.svg?style=flat-square)](https://travis-ci.org/dektrium/yii2-user) [![Packagist Version](https://img.shields.io/packagist/v/dektrium/yii2-user.svg?style=flat-square)](https://packagist.org/packages/dektrium/yii2-user) [![Total Downloads](https://img.shields.io/packagist/dt/dektrium/yii2-user.svg?style=flat-square)](https://packagist.org/packages/dektrium/yii2-user) [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md) +# Yii2-user [![Build Status](https://img.shields.io/travis/dabilite/yii2-user/master.svg?style=flat-square)](https://travis-ci.org/dabilite/yii2-user) [![Packagist Version](https://img.shields.io/packagist/v/dabilite/yii2-user.svg?style=flat-square)](https://packagist.org/packages/dabilite/yii2-user) [![Total Downloads](https://img.shields.io/packagist/dt/dabilite/yii2-user.svg?style=flat-square)](https://packagist.org/packages/dabilite/yii2-user) [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md) Most of web applications provide a way for users to register, log in or reset their forgotten passwords. Rather than re-implementing this on each application, @@ -34,6 +34,8 @@ If you have any questions or problems with Yii2-user you can ask them on [our fo Anyone and everyone is welcome to contribute. Please take a moment to review the [guidelines for contributing](.github/CONTRIBUTING.md). +Tests can be run locally via docker. +Simply run `docker-compose run --rm functional-tests` and all tests will be run. ## License diff --git a/composer.json b/composer.json index 53fbc0dc0..bca84c1de 100644 --- a/composer.json +++ b/composer.json @@ -1,33 +1,39 @@ { - "name": "dektrium/yii2-user", + "name": "dabilite/yii2-user", "description": "Flexible user registration and authentication module for Yii2", - "keywords": ["yii2", "yii2-user", "user management", "dektrium"], + "keywords": ["yii2", "yii2-user", "user management", "dektrium", "dabilite"], "type": "yii2-extension", "license": "MIT", "support": { - "issues": "https://github.com/dektrium/yii2-user/issues?state=open", - "forum": "https://gitter.im/dektrium/yii2-user", - "source": "https://github.com/dektrium/yii2-user" + "issues": "https://github.com/dabilite/yii2-user/issues?state=open", + "source": "https://github.com/dabilite/yii2-user" }, "authors": [ { "name": "Dmitry Erofeev", "email": "dmeroff@gmail.com", "homepage": "http://dmeroff.ru" + }, + { + "name": "Sam Mousa", + "email": "sam@mousa.nl", + "homepage": "https://www.linkedin.com/in/sam-mousa-16333820/" } ], - "minimum-stability": "dev", "require": { "yiisoft/yii2": "^2.0.0", "yiisoft/yii2-swiftmailer": "^2.0.0", "yiisoft/yii2-authclient": "^2.1.0", - "yiisoft/yii2-bootstrap": "^2.0.0" + "yiisoft/yii2-bootstrap": "^2.0.0", + "codeception/codeception": "^2.3" }, "require-dev": { - "yiisoft/yii2-codeception": "^2.0.0", "codeception/specify": "^0.4.3", "codeception/verify": "^0.3.1" }, + "provide": { + "dektrium/yii2-user": "0.9.12" + }, "autoload": { "psr-4": { "dektrium\\user\\": "" @@ -40,4 +46,4 @@ "dev-develop": "1.0.x-dev" } } -} +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..e7cc65888 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,64 @@ +version: '2' +services: + + +## Running tests + functional-tests: + extends: codeception + entrypoint: [ + "/sbin/tini", + "--", + "/bin/wait-for-it", + "-h", "$$MYSQL_HOST:3306", + "-t", "100", + "--", + "/project/tests/runtests.sh", + "run functional" + ] + depends_on: + - mysql + +# entrypoint: "ls /project" + +## Running unit tests + unit: + extends: codeception + entrypoint: [ + "/sbin/tini", + "--", + "/bin/wait-for-it", + "-h", "$$DB_HOST:3306", + "-t", "100", + "--", + "/project/tests/runtests.sh", + "run unit" + ] + depends_on: + - mysql +## Running codeception helper scripts. + codeception: + tty: true + image: sammousa/php-with-extensions + entrypoint: ["/sbin/tini", "--", "/project/tests/runtests.sh"] + volumes: + - ./:/project + environment: + MYSQL_ROOT_PASSWORD: secret + MYSQL_USER: dabilite + MYSQL_PASSWORD: testpass + MYSQL_DATABASE: test +# We set this to keep compatibility between gitlab-ci and docker compose + RUNNER_IP: web + MYSQL_HOST: mysql + YII_ENV: "test" +## Mysql server (local) + mysql: + image: mysql:5.7.14 + tmpfs: + - /var/lib/mysql + environment: + MYSQL_ROOT_PASSWORD: secret + MYSQL_USER: dabilite + MYSQL_PASSWORD: testpass + MYSQL_DATABASE: test + diff --git a/helpers/Timezone.php b/helpers/Timezone.php index 935940524..be5417d7a 100644 --- a/helpers/Timezone.php +++ b/helpers/Timezone.php @@ -31,10 +31,11 @@ public static function getAll() foreach ($timeZoneIdentifiers as $timeZone) { $date = new \DateTime('now', new \DateTimeZone($timeZone)); - $offset = $date->getOffset() / 60 / 60; + $offset = $date->getOffset(); + $tz = ($offset > 0 ? '+' : '-') . gmdate('H:i', abs($offset)); $timeZones[] = [ 'timezone' => $timeZone, - 'name' => "{$timeZone} (UTC " . ($offset > 0 ? '+' : '') . "{$offset})", + 'name' => "{$timeZone} (UTC " . "{$tz})", 'offset' => $offset ]; } diff --git a/messages/de/user.php b/messages/de/user.php index 65a0c76ab..959baae2a 100644 --- a/messages/de/user.php +++ b/messages/de/user.php @@ -35,6 +35,7 @@ 'An error occurred processing your request' => 'Ein Fehler ist aufgetreten', 'Assignments' => 'Zuordnungen', 'Are you sure you want to switch to this user for the rest of this Session?' => 'Sind Sie sicher, dass sie für den Rest der Sitzung zu diesem Benutzer wechseln möchten?', + 'Auth item' => 'Berechtigung', 'Awesome, almost there. Now you need to click the confirmation link sent to your new email address' => 'Fast geschafft. Nun müssen Sie nur noch den Aktivierungslink besuchen, der an ihre neue E-Mail Adresse gesendet wurde', 'Awesome, almost there. Now you need to click the confirmation link sent to your old email address' => 'Fast geschafft. Nun müssen Sie nur noch den Aktivierungslink besuchen, der an ihre alte E-Mail Adresse gesendet wurde', 'Become this user' => 'Zu diesem Nutzer wechseln', diff --git a/messages/it/user.php b/messages/it/user.php index 46f1351f1..927c19ee0 100644 --- a/messages/it/user.php +++ b/messages/it/user.php @@ -18,53 +18,41 @@ * NOTE: this file must be saved in UTF-8 encoding. */ return [ - 'Account details' => 'Dettagli account', - 'Account details have been updated' => 'I dettagli dell\'account sono stati aggiornati', - 'Are you sure you want to delete this user?' => 'Sei sicuro di voler eliminare questo utente?', - 'Assignments' => 'Assegnamenti', - 'Confirmation status' => 'Stato conferma', - 'Create' => 'Crea', - 'Delete' => 'Elimina', - 'Don\'t have an account? Sign up!' => 'Non hai ancora un account? Iscriviti!', - 'In order to finish your registration, we need you to enter your email address' => 'Per completare la registrazione devi inserire il tuo indirizzo email', - 'Information' => 'Info', - 'New permission' => 'Nuovi permessi', - 'New role' => 'Nuovo ruolo', - 'New user' => 'Nuovo utente', - 'Not blocked' => 'Non bloccato', - 'Permissions' => 'Permessi', - 'Profile details' => 'Dettagli profilo', - 'Profile details have been updated' => 'I dettagli del profilo sono stati aggiornati', - 'Recovery message sent' => 'Messaggio di recupero inviato', - 'Registration IP' => 'IP registrazione', - 'Roles' => 'Ruoli', - 'Something went wrong' => 'Qualcosa è andato storto', - 'Unconfirmed' => 'Non confermato', - 'Update' => 'Aggiorna', - 'VKontakte' => 'VKontakte', - 'Yandex' => 'Yandex', - 'You can assign multiple roles or permissions to user by using the form below' => 'Puoi assegnare più ruoli o permessi all\'utente usando il modulo sottostante', - 'You can connect multiple accounts to be able to log in using them' => 'Poi connettere più account ed usarli per per effettuare l\'accesso', + 'You can log-in to your account here: {login-url}' => 'Puoi accedere al tuo account qui: {login-url}', + 'Your username is' => 'Il tuo nome utente è', + 'A message has been sent to your email address. It contains a password that we generated for you.' => '@@È stato inviato un messaggio al tuo indirizzo email. Contiene la password che abbiamo generato per te.@@', + 'A message has been sent to your email address. It contains your password and a confirmation link that you must click to complete registration.' => '@@È stato inviato un messaggio al tuo indirizzo email. Contiene la password che abbiamo generato per te e un collegamento di attivazione che devi visitare per completare la registrazione.@@', + 'In order to finish your registration, we need you to enter your email address' => '@@Per completare la registrazione devi inserire il tuo indirizzo email@@', + 'There is no user with this email address' => '@@Non esiste nessun utente con questa email@@', + 'This account has already been confirmed' => '@@Questo account è già stato confermato@@', + 'Welcome! Registration is complete.' => '@@Benvenuto! La registrazione è completa.@@', + 'You can now log in with the following credentials:' => '@@Ora puoi collegarti con queste credenziali:@@', '(not set)' => '(non selezionato)', - 'A confirmation message has been sent to your new email address' => 'Un messaggio di conferma è stato inviato al tuo nuovo indirizzo email', - 'A message has been sent to your email address. It contains a confirmation link that you must click to complete registration.' => 'È stato inviato un messaggio al tuo indirizzo email. Contiene un collegamento di attivazione che devi visitare per completare la registrazione.', - 'A message has been sent to your email address. It contains a password that we generated for you.' => 'È stato inviato un messaggio al tuo indirizzo email. Contiene la password che abbiamo generato per te.', - 'A message has been sent to your email address. It contains your password and a confirmation link that you must click to complete registration.' => 'È stato inviato un messaggio al tuo indirizzo email. Contiene la password che abbiamo generato per te e un collegamento di attivazione che devi visitare per completare la registrazione.', - 'A new confirmation link has been sent' => 'Un nuovo collegamento di conferma è stato inviato', - 'A password will be generated automatically if not provided' => 'Una password verrà generata automaticamente se non fornita', + 'A confirmation message has been sent to your new email address' => 'Un messaggio di conferma è stato inviato al tuo nuovo indirizzo email', + 'A message has been sent to your email address. It contains a confirmation link that you must click to complete registration.' => 'È stato inviato un messaggio al tuo indirizzo email. Contiene un collegamento di attivazione che devi visitare per completare la registrazione.', + 'A new confirmation link has been sent' => 'Un nuovo collegamento di conferma è stato inviato', + 'A password will be generated automatically if not provided' => 'Una password verrà generata automaticamente se non fornita', 'Account' => 'Account', 'Account confirmation' => 'Conferma account', + 'Account details' => 'Dettagli account', + 'Account details have been updated' => 'I dettagli dell\'account sono stati aggiornati', 'Account settings' => 'Impostazioni account', - 'Already registered? Sign in!' => 'Già registrato? Accedi!', - 'An email has been sent with instructions for resetting your password' => 'È stata inviata un\'email con le istruzioni per il reset della password', - 'An error occurred and your password has not been changed. Please try again later.' => 'C\'è stato un errore e la tua password non è stata cambiata. Per favore riprova più tardi.', - 'An error occurred processing your request' => 'C\'è stato un errore nell\'elaborazione della tua richiesta', + 'Already registered? Sign in!' => 'Già registrato? Accedi!', + 'An email has been sent with instructions for resetting your password' => 'È stata inviata un\'email con le istruzioni per il reset della password', + 'An error occurred and your password has not been changed. Please try again later.' => 'C\'è stato un errore e la tua password non è stata cambiata. Per favore riprova più tardi.', + 'An error occurred processing your request' => 'C\'è stato un errore nell\'elaborazione della tua richiesta', 'Are you sure you want to block this user?' => 'Sicuro di voler bloccare questo utente?', 'Are you sure you want to confirm this user?' => 'Sicuro di voler confermare questo utente?', + 'Are you sure you want to delete this user?' => 'Sei sicuro di voler eliminare questo utente?', + 'Are you sure you want to switch to this user for the rest of this Session?' => 'Sei sicuro di voler passare a questo utente per il resto di questa sessione?', 'Are you sure you want to unblock this user?' => 'Sicuro di voler sbloccare questo utente?', - 'Are you sure? Deleted user can not be restored' => 'Sei sicuro? L\'utente non potrà essere ripristinato', + 'Are you sure?' => 'Sei sicuro?', + 'Are you sure? Deleted user can not be restored' => 'Sei sicuro? L\'utente non potrà essere ripristinato', + 'Are you sure? There is no going back' => 'Sei sicuro? Non è possibile annullare questa azione', + 'Assignments' => 'Assegnamenti', 'Awesome, almost there. Now you need to click the confirmation link sent to your new email address' => 'Bene, ci siamo quasi. Ora devi visitare il collegamento di conferma che abbiamo inviato al tuo nuovo indirizzo email.', 'Awesome, almost there. Now you need to click the confirmation link sent to your old email address' => 'Bene, ci siamo quasi. Ora devi visitare il collegamento di conferma che abbiamo inviato al tuo vecchio indirizzo email.', + 'Become this user' => 'Diventa questo utente', 'Bio' => 'Biografia', 'Block' => 'Blocca', 'Block status' => 'Stato del blocco', @@ -75,95 +63,138 @@ 'Confirm account on {0}' => 'Conferma l\'account su {0}', 'Confirm email change on {0}' => 'Conferma il cambio email su {0}', 'Confirmation' => 'Conferma', + 'Confirmation status' => 'Stato conferma', 'Confirmation time' => 'Orario di conferma', 'Confirmed' => 'Confermato', 'Confirmed at {0, date, MMMM dd, YYYY HH:mm}' => 'Confermato il {0, date, dd MMMM, YYYY HH:mm}', 'Connect' => 'Connetti', 'Continue' => 'Continua', + 'Create' => 'Crea', 'Create a user account' => 'Crea un account', 'Credentials will be sent to the user by email' => 'Le credenziali verranno inviate all\'utente via email', 'Current password' => 'Password attuale', - 'Current password is not valid' => 'La password corrente non è valida', + 'Current password is not valid' => 'La password corrente non è valida', + 'Delete' => 'Elimina', + 'Delete account' => 'Cancella account', 'Didn\'t receive confirmation message?' => 'Non hai ricevuto il messaggio di conferma?', 'Disconnect' => 'Disconnetti', + 'Don\'t have an account? Sign up!' => 'Non hai ancora un account? Iscriviti!', 'Email' => 'Email', 'Email (public)' => 'Email (pubblica)', - 'Error occurred while changing password' => 'Si è verificato un errore durante la modifica della password', - 'Error occurred while confirming user' => 'Si è verificato un errore durante la conferma utente', - 'Error occurred while deleting user' => 'Si è verificato un errore durante la rimozione dell\'utente!', + 'Error occurred while changing password' => 'Si è verificato un errore durante la modifica della password', + 'Error occurred while confirming user' => 'Si è verificato un errore durante la conferma utente', + 'Error occurred while deleting user' => 'Si è verificato un errore durante la rimozione dell\'utente!', + 'Error while trying to generate new password' => 'Errore durante la generazione di una nuova password', 'Finish' => 'Completa', 'Forgot password?' => 'Password dimenticata?', + 'Generate and send new password to user' => 'Genera ed invia una nuova password all\'utente', 'Gravatar email' => 'Email Gravatar', 'Hello' => 'Ciao', - 'If you already registered, sign in and connect this account on settings page' => 'Se sei già registrato, accedi e collegati alla pagina delle impostazioni', + 'If you already registered, sign in and connect this account on settings page' => 'Se sei già registrato, accedi e collegati alla pagina delle impostazioni', 'If you cannot click the link, please try pasting the text into your browser' => 'Se hai problemi, per favore incollare l\'URL sopra nella barra degli indirizzi', - 'If you did not make this request you can ignore this email' => 'P.S.: Se non hai richiesto di reimpostare la password, ignora questo messaggio. Il tuo account è al sicuro.', + 'If you did not make this request you can ignore this email' => 'P.S.: Se non hai richiesto di reimpostare la password, ignora questo messaggio. Il tuo account è al sicuro.', + 'Impersonate user is disabled in the application configuration' => 'Impersonare un utente è disabilitato nella configurazione dell\'applicazione', 'In order to complete your registration, please click the link below' => 'Per completare la registrazione, clicca sul link qui sotto', 'In order to complete your request, please click the link below' => 'Per completare la richiesta, clicca sul link qui sotto', + 'In order to finish your registration, we need you to enter following fields' => 'Per terminare la tua registrazione, abbiamo bisogno che tu inserisca i seguenti campi', + 'Information' => 'Info', 'Invalid login or password' => 'Login o Password errate', 'Invalid or expired link' => 'Collegamento non valido o scaduto', + 'It will be deleted forever' => 'Sarà cancellato in maniera irreversibile', 'Joined on {0, date}' => 'Registrato il {0, date}', - 'Location' => 'Località', + 'Last login' => 'Ultimo accesso', + 'Location' => 'Località', 'Login' => 'Entra', 'Logout' => 'Esci', 'Manage users' => 'Gestione utenti', 'Name' => 'Nome', 'Networks' => 'Rete', + 'Never' => 'Mai', + 'New Password has been generated and sent to user' => 'Una nuova password è stata generata e inviata all\'utente', 'New email' => 'Nuovo indirizzo email', 'New password' => 'Nuova password', + 'New permission' => 'Nuovi permessi', + 'New role' => 'Nuovo ruolo', + 'New rule' => 'Nuova regola', + 'New user' => 'Nuovo utente', + 'Not blocked' => 'Non bloccato', + 'Not found' => 'Non trovato', + 'Once you delete your account, there is no going back' => 'Una volta cancellato il tuo account, non è possibile tornare indietro', 'Password' => 'Password', - 'Password has been changed' => 'La password è stata modificata', + 'Password generation is not possible for admin users' => 'La generazione della password non è possibile per gli amministratori', + 'Password has been changed' => 'La password è stata modificata', + 'Password is not necessary because the module is in DEBUG mode.' => 'La password non è necessaria perché il modulo è in modalità DEBUG.', + 'Permissions' => 'Permessi', + 'Please be certain' => 'Per favore sii certo di volerlo fare', 'Please click the link below to complete your password reset' => 'Clicca il link qui sotto per completare la reimpostazione della password', 'Please fix following errors:' => 'Correggere i seguenti errori:', 'Profile' => 'Profilo', + 'Profile details' => 'Dettagli profilo', + 'Profile details have been updated' => 'I dettagli del profilo sono stati aggiornati', 'Profile settings' => 'Impostazioni Profilo', 'Recover your password' => 'Recupera password', - 'Recovery link is invalid or expired. Please try requesting a new one.' => 'Il collegamento di ripristino non è valido o è scaduto. Prova a richiederlo di nuovo.', + 'Recovery link is invalid or expired. Please try requesting a new one.' => 'Il collegamento di ripristino non è valido o è scaduto. Prova a richiederlo di nuovo.', + 'Recovery message sent' => 'Messaggio di recupero inviato', + 'Registration IP' => 'IP registrazione', 'Registration ip' => 'IP registrazione', + 'Registration on this website is disabled' => 'La registrazione su questo sito è disabilitata', 'Registration time' => 'Data registrazione', 'Remember me next time' => 'Ricordami', 'Request new confirmation message' => 'Richiedi nuovo messaggio di conferma', 'Reset your password' => 'Reset password', + 'Roles' => 'Ruoli', + 'Rules' => 'Regole', 'Save' => 'Salva', 'Sign in' => 'Accedi', 'Sign up' => 'Registrati', - 'Something went wrong and your account has not been confirmed.' => 'Qualcosa è andato storto e il tuo account non è stato confermato.', + 'Something went wrong' => 'Qualcosa è andato storto', + 'Something went wrong and your account has not been confirmed.' => 'Qualcosa è andato storto e il tuo account non è stato confermato.', 'Thank you for signing up on {0}' => 'Grazie per esserti iscritto su {0}', - 'Thank you, registration is now complete.' => 'Grazie, la registrazione è stata completata.', - 'The confirmation link is invalid or expired. Please try requesting a new one.' => 'Il collegamento di conferma non è valido o è scaduto. Prova a richiederlo di nuovo.', - 'There is no user with this email address' => 'Non esiste nessun utente con questa email', - 'This account has already been confirmed' => 'Questo account è già stato confermato', - 'This account has already been connected to another user' => 'Questo account è già stato collegato a un altro utente', - 'This email address has already been taken' => 'Questo indirizzo email è già stato utilizzato', - 'This username has already been taken' => 'Questo nome utente è già stato utilizzato', + 'Thank you, registration is now complete.' => 'Grazie, la registrazione è stata completata.', + 'The confirmation link is invalid or expired. Please try requesting a new one.' => 'Il collegamento di conferma non è valido o è scaduto. Prova a richiederlo di nuovo.', + 'This account has already been connected to another user' => 'Questo account è già stato collegato a un altro utente', + 'This email address has already been taken' => 'Questo indirizzo email è già stato utilizzato', + 'This username has already been taken' => 'Questo nome utente è già stato utilizzato', + 'Time zone' => 'Fuso orario', + 'Time zone is not valid' => 'Il fuso orario non è valido', 'Unblock' => 'Sblocca', + 'Unconfirmed' => 'Non confermato', + 'Update' => 'Aggiorna', 'Update user account' => 'Aggiorna account utente', - 'User has been blocked' => 'L\'utente è stato bloccato', - 'User has been confirmed' => 'L\'utente è stato confermato', - 'User has been created' => 'L\'utente è stato creato', - 'User has been deleted' => 'L\'utente è stato rimosso', - 'User has been unblocked' => 'L\'utente è stato sbloccato', + 'User has been blocked' => 'L\'utente è stato bloccato', + 'User has been confirmed' => 'L\'utente è stato confermato', + 'User has been created' => 'L\'utente è stato creato', + 'User has been deleted' => 'L\'utente è stato rimosso', + 'User has been unblocked' => 'L\'utente è stato sbloccato', 'User is not found' => 'Utente non trovato', 'Username' => 'Nome utente', 'Users' => 'Utenti', + 'VKontakte' => 'VKontakte', + 'We have generated a password for you' => 'Abbiamo generato una password per te', 'We have received a request to change the email address for your account on {0}' => 'Abbiamo ricevuto una richiesta di cambio email per il tuo account su {0}', 'We have received a request to reset the password for your account on {0}' => 'Abbiamo ricevuto una richiesta di reset password su {0}', 'We have sent confirmation links to both old and new email addresses. You must click both links to complete your request' => 'Abbiamo inviato un collegamento di conferma sia al vecchio che al nuovo indirizzo email. Devi visitare entrambi i collegamenti per completare la richiesta', 'Website' => 'Sito web', 'Welcome to {0}' => 'Benvenuto su {0}', - 'Welcome! Registration is complete.' => 'Benvenuto! La registrazione è completa.', + 'Yandex' => 'Yandex', + 'You can assign multiple roles or permissions to user by using the form below' => 'Puoi assegnare più ruoli o permessi all\'utente usando il modulo sottostante', + 'You can connect multiple accounts to be able to log in using them' => 'Poi connettere più account ed usarli per per effettuare l\'accesso', 'You can not block your own account' => 'Non puoi bloccare il tuo account', 'You can not remove your own account' => 'Non puoi rimuovere il tuo account', - 'You can now log in with the following credentials:' => 'Ora puoi collegarti con queste credenziali:', 'You need to confirm your email address' => 'Devi confermare il tuo indirizzo email', 'Your account details have been updated' => 'I dettagli del tuo account sono stati aggiornati', - 'Your account has been blocked' => 'Il tuo account è stato bloccato', - 'Your account has been connected' => 'Il tuo account è stato collegato', - 'Your account has been created' => 'Il tuo profilo è stato creato', - 'Your account on {0} has been created' => 'Il tuo account su {0} è stato creato', - 'Your confirmation token is invalid or expired' => 'Il tuo token di conferma non è valido o è scaduto', - 'Your email address has been changed' => 'Il tuo indirizzo email è stato cambiato', - 'Your password has been changed successfully.' => 'La tua password è stata cambiata con successo.', - 'Your profile has been updated' => 'Il tuo profilo è stato aggiornato', + 'Your account has been blocked' => 'Il tuo account è stato bloccato', + 'Your account has been blocked.' => 'Il tuo account è stato bloccato.', + 'Your account has been completely deleted' => 'Il tuo account è stato completamente cancellato', + 'Your account has been connected' => 'Il tuo account è stato collegato', + 'Your account has been created' => 'Il tuo profilo è stato creato', + 'Your account has been created and a message with further instructions has been sent to your email' => 'Il tuo account è stato creato e un messaggio con ulteriori istruzioni è stato mandato al tuo indirizzo email', + 'Your account on {0} has a new password' => 'Il tuo account su {0} ha una nuova password', + 'Your account on {0} has been created' => 'Il tuo account su {0} è stato creato', + 'Your confirmation token is invalid or expired' => 'Il tuo token di conferma non è valido o è scaduto', + 'Your email address has been changed' => 'Il tuo indirizzo email è stato cambiato', + 'Your password has been changed successfully.' => 'La tua password è stata cambiata con successo.', + 'Your password on {0} has been changed' => 'La tua password su {0} è stata cambiata', + 'Your profile has been updated' => 'Il tuo profilo è stato aggiornato', '{0, date, MMMM dd, YYYY HH:mm}' => '{0, date, dd MMMM, YYYY HH:mm}', ]; diff --git a/models/User.php b/models/User.php index cc0abf42b..74afd957d 100644 --- a/models/User.php +++ b/models/User.php @@ -126,6 +126,17 @@ public function getIsAdmin() || in_array($this->username, $this->module->admins); } + /** + * Wrapper function to retrieve authorization items of the current user. + * + * @return mixed return the assigned authorization items of the current user. When no authManager is configured, + * it returns an empty array since by definition there are no authorization items for the current (or any) user. + */ + public function getAuthItems() + { + return \Yii::$app->authManager ? \Yii::$app->authManager->getItemsByUser($this->id) : []; + } + /** * @return \yii\db\ActiveQuery */ @@ -187,6 +198,7 @@ public function getAuthKey() public function attributeLabels() { return [ + 'auth_item' => \Yii::t('user', 'Auth item'), 'username' => \Yii::t('user', 'Username'), 'email' => \Yii::t('user', 'Email'), 'registration_ip' => \Yii::t('user', 'Registration ip'), diff --git a/models/UserSearch.php b/models/UserSearch.php index 89075d1fe..6a2a75e8a 100644 --- a/models/UserSearch.php +++ b/models/UserSearch.php @@ -39,6 +39,9 @@ class UserSearch extends Model /** @var string */ public $registration_ip; + /** @var string in case DbManager is used, we can filter users by auth_item in the admin/index view */ + public $auth_item; + /** @var Finder */ protected $finder; @@ -56,7 +59,8 @@ public function __construct(Finder $finder, $config = []) public function rules() { return [ - 'fieldsSafe' => [['id', 'username', 'email', 'registration_ip', 'created_at', 'last_login_at'], 'safe'], + + 'fieldsSafe' => [['id', 'username', 'email', 'registration_ip', 'created_at', 'last_login_at', 'auth_item'], 'safe'], 'createdDefault' => ['created_at', 'default', 'value' => null], 'lastloginDefault' => ['last_login_at', 'default', 'value' => null], ]; @@ -93,7 +97,14 @@ public function search($params) return $dataProvider; } - $table_name = $query->modelClass::tableName(); + if (\Yii::$app->authManager instanceof yii\rbac\DbManager && $this->auth_item) { + $assignment_table = \Yii::$app->authManager->assignmentTable; + $query->leftJoin($assignment_table, $assignment_table.'.user_id = user.id'); + $query->andFilterWhere(['item_name' => $this->auth_item]); + } + + $model = $query->modelClass; + $table_name = $model::tableName(); if ($this->created_at !== null) { $date = strtotime($this->created_at); diff --git a/tests/_app/config/db.php b/tests/_app/config/db.php index 24b10a453..3fbdcc784 100644 --- a/tests/_app/config/db.php +++ b/tests/_app/config/db.php @@ -2,14 +2,11 @@ $db = [ 'class' => 'yii\db\Connection', - 'dsn' => 'mysql:host=localhost;dbname=dektrium_test', - 'username' => 'root', - 'password' => '', + 'dsn' => 'mysql:host=' . getenv('MYSQL_HOST') . ';dbname=' . getenv('MYSQL_DATABASE'), + 'password' => getenv('MYSQL_PASSWORD'), + 'username' => getenv('MYSQL_USER'), 'charset' => 'utf8', +// 'enableSavepoint' => false ]; -if (file_exists(__DIR__ . '/db.local.php')) { - $db = array_merge($db, require(__DIR__ . '/db.local.php')); -} - return $db; \ No newline at end of file diff --git a/tests/_app/config/test.php b/tests/_app/config/test.php index 92b3aca4d..7371a186e 100644 --- a/tests/_app/config/test.php +++ b/tests/_app/config/test.php @@ -18,6 +18,9 @@ ], ], 'components' => [ + 'assetManager' => [ + 'basePath' => '/tmp' + ], 'db' => require __DIR__ . '/db.php', 'mailer' => [ 'useFileTransport' => true, diff --git a/tests/_fixtures/ActiveFixture.php b/tests/_fixtures/ActiveFixture.php new file mode 100644 index 000000000..4b6d428d1 --- /dev/null +++ b/tests/_fixtures/ActiveFixture.php @@ -0,0 +1,24 @@ +getTableSchema(); + $this->db->createCommand()->delete($table->fullName)->execute(); + } +} \ No newline at end of file diff --git a/tests/_fixtures/ProfileFixture.php b/tests/_fixtures/ProfileFixture.php index 2b872af65..19724bd4e 100644 --- a/tests/_fixtures/ProfileFixture.php +++ b/tests/_fixtures/ProfileFixture.php @@ -2,8 +2,6 @@ namespace tests\_fixtures; -use yii\test\ActiveFixture; - class ProfileFixture extends ActiveFixture { public $modelClass = 'dektrium\user\models\Profile'; @@ -11,4 +9,6 @@ class ProfileFixture extends ActiveFixture public $depends = [ 'tests\_fixtures\UserFixture' ]; + + } diff --git a/tests/_fixtures/TokenFixture.php b/tests/_fixtures/TokenFixture.php index 72f5084b4..f9879006e 100644 --- a/tests/_fixtures/TokenFixture.php +++ b/tests/_fixtures/TokenFixture.php @@ -2,8 +2,6 @@ namespace tests\_fixtures; -use yii\test\ActiveFixture; - class TokenFixture extends ActiveFixture { public $modelClass = 'dektrium\user\models\Token'; diff --git a/tests/_fixtures/UserFixture.php b/tests/_fixtures/UserFixture.php index f9894309d..747a196ae 100644 --- a/tests/_fixtures/UserFixture.php +++ b/tests/_fixtures/UserFixture.php @@ -2,8 +2,6 @@ namespace tests\_fixtures; -use yii\test\ActiveFixture; - class UserFixture extends ActiveFixture { public $modelClass = 'dektrium\user\models\User'; diff --git a/tests/_fixtures/data/user.php b/tests/_fixtures/data/user.php index 6c9e98d7c..3eeeecc36 100644 --- a/tests/_fixtures/data/user.php +++ b/tests/_fixtures/data/user.php @@ -4,6 +4,7 @@ return [ 'user' => [ + 'id' => 1, 'username' => 'user', 'email' => 'user@example.com', 'password_hash' => '$2y$13$qY.ImaYBppt66qez6B31QO92jc5DYVRzo5NxM1ivItkW74WsSG6Ui', @@ -13,6 +14,7 @@ 'confirmed_at' => $time, ], 'unconfirmed' => [ + 'id' => 2, 'username' => 'joe', 'email' => 'joe@example.com', 'password_hash' => '$2y$13$CIH1LSMPzU9xDCywt3QO8uovAu2axp8hwuXVa72oI.1G/USsGyMBS', @@ -21,6 +23,7 @@ 'updated_at' => $time, ], 'unconfirmed_with_expired_token' => [ + 'id' => 3, 'username' => 'john', 'email' => 'john@example.com', 'password_hash' => '$2y$13$qY.ImaYBppt66qez6B31QO92jc5DYVRzo5NxM1ivItkW74WsSG6Ui', @@ -29,6 +32,7 @@ 'updated_at' => $time - 86401, ], 'blocked' => [ + 'id' => 4, 'username' => 'steven', 'email' => 'steven@example.com', 'password_hash' => '$2y$13$qY.ImaYBppt66qez6B31QO92jc5DYVRzo5NxM1ivItkW74WsSG6Ui', @@ -39,6 +43,7 @@ 'confirmed_at' => $time, ], 'user_with_expired_recovery_token' => [ + 'id' => 5, 'username' => 'andrew', 'email' => 'andrew@example.com', 'password_hash' => '$2y$13$qY.ImaYBppt66qez6B31QO92jc5DYVRzo5NxM1ivItkW74WsSG6Ui', @@ -48,6 +53,7 @@ 'confirmed_at' => $time - 21601, ], 'user_with_recovery_token' => [ + 'id' => 6, 'username' => 'alex', 'email' => 'alex@example.com', 'password_hash' => '$2y$13$qY.ImaYBppt66qez6B31QO92jc5DYVRzo5NxM1ivItkW74WsSG6Ui', diff --git a/tests/_pages/AdminPage.php b/tests/_pages/AdminPage.php index e6affaea1..4c9778f21 100644 --- a/tests/_pages/AdminPage.php +++ b/tests/_pages/AdminPage.php @@ -2,8 +2,6 @@ namespace tests\_pages; -use yii\codeception\BasePage; - /** * Represents admin page. * diff --git a/tests/_pages/BasePage.php b/tests/_pages/BasePage.php new file mode 100644 index 000000000..6086c068d --- /dev/null +++ b/tests/_pages/BasePage.php @@ -0,0 +1,60 @@ + 'about')`. + */ + public $route; + /** + * @var \Codeception\Actor the testing guy object + */ + protected $actor; + + /** + * Constructor. + * + * @param \Codeception\Actor $I the testing guy object + */ + public function __construct($I) + { + $this->actor = $I; + } + + /** + * Returns the URL to this page. + * The URL will be returned by calling the URL manager of the application + * with [[route]] and the provided parameters. + * @param array $params the GET parameters for creating the URL + * @return string the URL to this page + * @throws InvalidConfigException if [[route]] is not set or invalid + */ + public function getUrl($params = []) + { + if (is_string($this->route)) { + $params[0] = $this->route; + return Yii::$app->getUrlManager()->createUrl($params); + } elseif (is_array($this->route) && isset($this->route[0])) { + return Yii::$app->getUrlManager()->createUrl(array_merge($this->route, $params)); + } else { + throw new InvalidConfigException('The "route" property must be set.'); + } + } + + /** + * Creates a page instance and sets the test guy to use [[url]]. + * @param \Codeception\Actor $I the test guy instance + * @param array $params the GET parameters to be used to generate [[url]] + * @return static the page instance + */ + public static function openBy($I, $params = []) + { + $page = new static($I); + $I->amOnPage($page->getUrl($params)); + return $page; + } +} diff --git a/tests/_pages/CreatePage.php b/tests/_pages/CreatePage.php index 503b06108..0b937f214 100644 --- a/tests/_pages/CreatePage.php +++ b/tests/_pages/CreatePage.php @@ -2,8 +2,6 @@ namespace tests\_pages; -use yii\codeception\BasePage; - /** * Represents admin create page. * diff --git a/tests/_pages/LoginPage.php b/tests/_pages/LoginPage.php index 1095d6aef..3055ddd4e 100644 --- a/tests/_pages/LoginPage.php +++ b/tests/_pages/LoginPage.php @@ -2,8 +2,6 @@ namespace tests\_pages; -use yii\codeception\BasePage; - /** * Represents login page. * diff --git a/tests/_pages/RecoveryPage.php b/tests/_pages/RecoveryPage.php index 25a33de73..88ce67004 100644 --- a/tests/_pages/RecoveryPage.php +++ b/tests/_pages/RecoveryPage.php @@ -2,8 +2,6 @@ namespace tests\_pages; -use yii\codeception\BasePage; - /** * Represents resend page. * diff --git a/tests/_pages/RegistrationPage.php b/tests/_pages/RegistrationPage.php index 0387d7ff6..2f1721904 100644 --- a/tests/_pages/RegistrationPage.php +++ b/tests/_pages/RegistrationPage.php @@ -2,8 +2,6 @@ namespace tests\_pages; -use yii\codeception\BasePage; - /** * Represents registration page. * diff --git a/tests/_pages/ResendPage.php b/tests/_pages/ResendPage.php index 2753e1fec..4098e4ac2 100644 --- a/tests/_pages/ResendPage.php +++ b/tests/_pages/ResendPage.php @@ -2,8 +2,6 @@ namespace tests\_pages; -use yii\codeception\BasePage; - /** * Represents resend page. * diff --git a/tests/_pages/SettingsPage.php b/tests/_pages/SettingsPage.php index 5d7cc2876..f3b0b85f4 100644 --- a/tests/_pages/SettingsPage.php +++ b/tests/_pages/SettingsPage.php @@ -2,8 +2,6 @@ namespace tests\_pages; -use yii\codeception\BasePage; - /** * Represents email settings page. * diff --git a/tests/_pages/UpdatePage.php b/tests/_pages/UpdatePage.php index 0819f8219..24465c64d 100644 --- a/tests/_pages/UpdatePage.php +++ b/tests/_pages/UpdatePage.php @@ -2,8 +2,6 @@ namespace tests\_pages; -use yii\codeception\BasePage; - /** * Represents admin update page. * diff --git a/tests/runtests.sh b/tests/runtests.sh new file mode 100755 index 000000000..8827acbbb --- /dev/null +++ b/tests/runtests.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +composer install --prefer-dist + +php tests/_app/yii.php migrate --migrationPath=@dektrium/user/migrations --interactive=0 + +exec /bin/codecept $@ \ No newline at end of file diff --git a/traits/ModuleTrait.php b/traits/ModuleTrait.php index c2031a942..1d7a0d342 100644 --- a/traits/ModuleTrait.php +++ b/traits/ModuleTrait.php @@ -19,4 +19,9 @@ public function getModule() { return \Yii::$app->getModule('user'); } + + public static function getDb() + { + return \Yii::$app->getModule('user')->getDb(); + } } diff --git a/views/admin/index.php b/views/admin/index.php index ebb063d51..bdc2384c6 100644 --- a/views/admin/index.php +++ b/views/admin/index.php @@ -10,12 +10,12 @@ */ use yii\grid\GridView; +use yii\helpers\ArrayHelper; use yii\helpers\Html; use yii\helpers\Url; use yii\web\View; use yii\widgets\Pjax; - /** * @var \yii\web\View $this * @var \yii\data\ActiveDataProvider $dataProvider @@ -62,7 +62,6 @@ } }, ], - [ 'attribute' => 'last_login_at', 'value' => function ($model) { @@ -75,6 +74,21 @@ } }, ], + [ + 'attribute' => 'auth_item', + 'format' => 'html', + 'value' => function ($data) { + return implode(', ', array_map(function ($ai) { + return $ai->name; + }, $data->authItems)); + }, + 'filter' => \Yii::$app->authManager instanceof yii\rbac\DbManager ? ArrayHelper::map(array_merge( + Yii::$app->authManager->getRoles(), + Yii::$app->authManager->getPermissions() + ), + 'name', 'name') : null, + 'visible' => Yii::$app->get('authManager') instanceof yii\rbac\ManagerInterface, + ], [ 'header' => Yii::t('user', 'Confirmation'), 'value' => function ($model) { @@ -125,7 +139,7 @@ } }, 'switch' => function ($url, $model) { - if($model->id != Yii::$app->user->id && Yii::$app->getModule('user')->enableImpersonateUser) { + if(!$model->isAdmin && $model->id != Yii::$app->user->id && Yii::$app->getModule('user')->enableImpersonateUser) { return Html::a('', ['/user/admin/switch', 'id' => $model->id], [ 'title' => Yii::t('user', 'Become this user'), 'data-confirm' => Yii::t('user', 'Are you sure you want to switch to this user for the rest of this Session?'), diff --git a/views/mail/text/welcome.php b/views/mail/text/welcome.php index a9f208c87..a3cd3e510 100644 --- a/views/mail/text/welcome.php +++ b/views/mail/text/welcome.php @@ -9,13 +9,16 @@ * file that was distributed with this source code. */ + /** - * @var dektrium\user\models\User + * @var dektrium\user\models\User $user */ ?> , name) ?>. +: +username?> enableGeneratingPassword): ?> : password ?> @@ -27,6 +30,8 @@ url ?> . + +\Yii::$app->urlManager->createAbsoluteUrl(['user/security/login'])]) ?> . diff --git a/views/mail/welcome.php b/views/mail/welcome.php index 2ed3f9c2f..139899eee 100644 --- a/views/mail/welcome.php +++ b/views/mail/welcome.php @@ -11,6 +11,7 @@ use yii\helpers\Html; + /** * @var dektrium\user\Module $module * @var dektrium\user\models\User $user @@ -24,6 +25,10 @@

name) ?>. +

+ +

+ : username?>
enableGeneratingPassword): ?> : password ?> @@ -40,6 +45,11 @@

.

+ +

+ Html::a(Html::encode(\Yii::$app->urlManager->createAbsoluteUrl(['user/security/login'])), \Yii::$app->urlManager->createAbsoluteUrl(['user/security/login']))]) ?> +

+