mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-09 12:42:36 +01:00
Finalize basic client portal password support
This commit is contained in:
parent
903904d423
commit
793ba76415
@ -1,127 +0,0 @@
|
||||
<?php namespace App\Http\Controllers\Auth;
|
||||
|
||||
use Auth;
|
||||
use Event;
|
||||
use Utils;
|
||||
use Session;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\User;
|
||||
use App\Events\UserLoggedIn;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Ninja\Repositories\AccountRepository;
|
||||
use App\Services\AuthService;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Contracts\Auth\Registrar;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
|
||||
|
||||
class ClientAuthController extends Controller {
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Registration & Login Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller handles the registration of new users, as well as the
|
||||
| authentication of existing users. By default, this controller uses
|
||||
| a simple trait to add these behaviors. Why don't you explore it?
|
||||
|
|
||||
*/
|
||||
|
||||
use AuthenticatesAndRegistersUsers;
|
||||
|
||||
protected $loginPath = '/client/login';
|
||||
protected $redirectTo = '/client/dashboard';
|
||||
protected $guard = 'contact';
|
||||
protected $authService;
|
||||
protected $accountRepo;
|
||||
|
||||
/**
|
||||
* Create a new authentication controller instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Guard $auth
|
||||
* @param \Illuminate\Contracts\Auth\Registrar $registrar
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Guard $auth, Registrar $registrar, AccountRepository $repo, AuthService $authService)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
$this->registrar = $registrar;
|
||||
$this->accountRepo = $repo;
|
||||
$this->authService = $authService;
|
||||
|
||||
//$this->middleware('guest', ['except' => 'getLogout']);
|
||||
}
|
||||
|
||||
public function authLogin($provider, Request $request)
|
||||
{
|
||||
return $this->authService->execute($provider, $request->has('code'));
|
||||
}
|
||||
|
||||
public function authUnlink()
|
||||
{
|
||||
$this->accountRepo->unlinkUserFromOauth(Auth::user());
|
||||
|
||||
Session::flash('message', trans('texts.updated_settings'));
|
||||
return redirect()->to('/settings/' . ACCOUNT_USER_DETAILS);
|
||||
}
|
||||
|
||||
public function getLoginWrapper()
|
||||
{
|
||||
if (!Utils::isNinja() && !User::count()) {
|
||||
return redirect()->to('invoice_now');
|
||||
}
|
||||
|
||||
return self::getLogin();
|
||||
}
|
||||
|
||||
public function postLoginWrapper(Request $request)
|
||||
{
|
||||
|
||||
$userId = Auth::check() ? Auth::user()->id : null;
|
||||
$user = User::where('email', '=', $request->input('email'))->first();
|
||||
|
||||
if ($user && $user->failed_logins >= MAX_FAILED_LOGINS) {
|
||||
Session::flash('error', trans('texts.invalid_credentials'));
|
||||
return redirect()->to('login');
|
||||
}
|
||||
|
||||
$response = self::postLogin($request);
|
||||
|
||||
if (Auth::check()) {
|
||||
Event::fire(new UserLoggedIn());
|
||||
|
||||
$users = false;
|
||||
// we're linking a new account
|
||||
if ($request->link_accounts && $userId && Auth::user()->id != $userId) {
|
||||
$users = $this->accountRepo->associateAccounts($userId, Auth::user()->id);
|
||||
Session::flash('message', trans('texts.associated_accounts'));
|
||||
// check if other accounts are linked
|
||||
} else {
|
||||
$users = $this->accountRepo->loadAccounts(Auth::user()->id);
|
||||
}
|
||||
Session::put(SESSION_USER_ACCOUNTS, $users);
|
||||
|
||||
} elseif ($user) {
|
||||
$user->failed_logins = $user->failed_logins + 1;
|
||||
$user->save();
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
public function getLogoutWrapper()
|
||||
{
|
||||
if (Auth::check() && !Auth::user()->registered) {
|
||||
$account = Auth::user()->account;
|
||||
$this->accountRepo->unlinkAccount($account);
|
||||
$account->forceDelete();
|
||||
}
|
||||
|
||||
$response = self::getLogout();
|
||||
|
||||
Session::flush();
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
62
app/Http/Controllers/ClientAuth/AuthController.php
Normal file
62
app/Http/Controllers/ClientAuth/AuthController.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php namespace App\Http\Controllers\ClientAuth;
|
||||
|
||||
use Auth;
|
||||
use Event;
|
||||
use Utils;
|
||||
use Session;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\User;
|
||||
use App\Events\UserLoggedIn;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Ninja\Repositories\AccountRepository;
|
||||
use App\Services\AuthService;
|
||||
use App\Models\Invitation;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
|
||||
class AuthController extends Controller {
|
||||
|
||||
protected $guard = 'client';
|
||||
protected $redirectTo = '/client/dashboard';
|
||||
|
||||
use AuthenticatesUsers;
|
||||
|
||||
public function showLoginForm()
|
||||
{
|
||||
return view('clientauth.login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the needed authorization credentials from the request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
protected function getCredentials(Request $request)
|
||||
{
|
||||
$credentials = $request->only('password');
|
||||
$credentials['id'] = null;
|
||||
|
||||
$invitation_key = session('invitation_key');
|
||||
if($invitation_key){
|
||||
$invitation = Invitation::where('invitation_key', '=', $invitation_key)->first();
|
||||
if ($invitation && !$invitation->is_deleted) {
|
||||
$credentials['id'] = $invitation->contact_id;
|
||||
}
|
||||
}
|
||||
|
||||
return $credentials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the user login request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return void
|
||||
*/
|
||||
protected function validateLogin(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'password' => 'required',
|
||||
]);
|
||||
}
|
||||
}
|
168
app/Http/Controllers/ClientAuth/PasswordController.php
Normal file
168
app/Http/Controllers/ClientAuth/PasswordController.php
Normal file
@ -0,0 +1,168 @@
|
||||
<?php namespace App\Http\Controllers\ClientAuth;
|
||||
|
||||
use Config;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Brokers\ClientPasswordBroker;
|
||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Mail\Message;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use App\Models\Invitation;
|
||||
|
||||
|
||||
class PasswordController extends Controller {
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Reset Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller is responsible for handling password reset requests
|
||||
| and uses a simple trait to include this behavior. You're free to
|
||||
| explore this trait and override any methods you wish to tweak.
|
||||
|
|
||||
*/
|
||||
|
||||
use ResetsPasswords;
|
||||
|
||||
protected $redirectTo = '/client/dashboard';
|
||||
|
||||
/**
|
||||
* Create a new password controller instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Auth\Guard $auth
|
||||
* @param \Illuminate\Contracts\Auth\PasswordBroker $passwords
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest');
|
||||
Config::set("auth.defaults.passwords","client");
|
||||
}
|
||||
|
||||
public function showLinkRequestForm()
|
||||
{
|
||||
return view('clientauth.password');
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a reset link to the given user.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function sendResetLinkEmail(Request $request)
|
||||
{
|
||||
$broker = $this->getBroker();
|
||||
|
||||
$contact_id = null;
|
||||
$invitation_key = session('invitation_key');
|
||||
if($invitation_key){
|
||||
$invitation = Invitation::where('invitation_key', '=', $invitation_key)->first();
|
||||
if ($invitation && !$invitation->is_deleted) {
|
||||
$contact_id = $invitation->contact_id;
|
||||
}
|
||||
}
|
||||
|
||||
$response = Password::broker($broker)->sendResetLink(array('id'=>$contact_id), function (Message $message) {
|
||||
$message->subject($this->getEmailSubject());
|
||||
});
|
||||
|
||||
switch ($response) {
|
||||
case Password::RESET_LINK_SENT:
|
||||
return $this->getSendResetLinkEmailSuccessResponse($response);
|
||||
|
||||
case Password::INVALID_USER:
|
||||
default:
|
||||
return $this->getSendResetLinkEmailFailureResponse($response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the password reset view for the given token.
|
||||
*
|
||||
* If no token is present, display the link request form.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string|null $invitation_key
|
||||
* @param string|null $token
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function showResetForm(Request $request, $invitation_key = null, $token = null)
|
||||
{
|
||||
if (is_null($token)) {
|
||||
return $this->getEmail();
|
||||
}
|
||||
|
||||
return view('clientauth.reset')->with(compact('token', 'invitation_key'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Display the password reset view for the given token.
|
||||
*
|
||||
* If no token is present, display the link request form.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param string|null $invitation_key
|
||||
* @param string|null $token
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function getReset(Request $request, $invitation_key = null, $token = null)
|
||||
{
|
||||
return $this->showResetForm($request, $invitation_key, $token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the given user's password.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function reset(Request $request)
|
||||
{
|
||||
$this->validate($request, $this->getResetValidationRules());
|
||||
|
||||
$credentials = $request->only(
|
||||
'password', 'password_confirmation', 'token'
|
||||
);
|
||||
|
||||
$credentials['id'] = null;
|
||||
|
||||
$invitation_key = $request->input('invitation_key');
|
||||
if($invitation_key){
|
||||
$invitation = Invitation::where('invitation_key', '=', $invitation_key)->first();
|
||||
if ($invitation && !$invitation->is_deleted) {
|
||||
$credentials['id'] = $invitation->contact_id;
|
||||
}
|
||||
}
|
||||
|
||||
$broker = $this->getBroker();
|
||||
|
||||
$response = Password::broker($broker)->reset($credentials, function ($user, $password) {
|
||||
$this->resetPassword($user, $password);
|
||||
});
|
||||
|
||||
switch ($response) {
|
||||
case Password::PASSWORD_RESET:
|
||||
return $this->getResetSuccessResponse($response);
|
||||
|
||||
default:
|
||||
return $this->getResetFailureResponse($request, $response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the password reset validation rules.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getResetValidationRules()
|
||||
{
|
||||
return [
|
||||
'token' => 'required',
|
||||
'password' => 'required|confirmed|min:6',
|
||||
];
|
||||
}
|
||||
}
|
@ -1,28 +1,13 @@
|
||||
<?php namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Auth;
|
||||
use Session;
|
||||
use App\Models\Invitation;
|
||||
use App\Models\Contact;
|
||||
use App\Models\Account;
|
||||
|
||||
class Authenticate {
|
||||
|
||||
/**
|
||||
* The Guard implementation.
|
||||
*
|
||||
* @var Guard
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
/**
|
||||
* Create a new filter instance.
|
||||
*
|
||||
* @param Guard $auth
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Guard $auth)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
@ -30,9 +15,45 @@ class Authenticate {
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
public function handle($request, Closure $next, $guard = 'user')
|
||||
{
|
||||
if ($this->auth->guest())
|
||||
$authenticated = Auth::guard($guard)->check();
|
||||
|
||||
if($guard == 'client' && !empty($request->invitation_key)){
|
||||
$old_key = session('invitation_key');
|
||||
if($old_key && $old_key != $request->invitation_key){
|
||||
if($this->getInvitationContactId($old_key) != $this->getInvitationContactId($request->invitation_key)){
|
||||
// This is a different client; reauthenticate
|
||||
$authenticated = false;
|
||||
Auth::guard($guard)->logout();
|
||||
}
|
||||
}
|
||||
Session::put('invitation_key', $request->invitation_key);
|
||||
}
|
||||
|
||||
if($guard=='client'){
|
||||
|
||||
if(Auth::guard('user')->check()){
|
||||
// This is an admin; let them pretend to be a client
|
||||
$authenticated = true;
|
||||
}
|
||||
|
||||
// Does this account require portal passwords?
|
||||
$invitation_key = session('invitation_key');
|
||||
$account = Account::whereId($this->getInvitationAccountId($invitation_key))->first();
|
||||
if(!$account->enable_portal_password || !$account->isPro()){
|
||||
$authenticated = true;
|
||||
}
|
||||
|
||||
if(!$authenticated){
|
||||
$contact = Contact::whereId($this->getInvitationContactId($invitation_key))->first();
|
||||
if($contact && !$contact->password){
|
||||
$authenticated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$authenticated)
|
||||
{
|
||||
if ($request->ajax())
|
||||
{
|
||||
@ -40,11 +61,30 @@ class Authenticate {
|
||||
}
|
||||
else
|
||||
{
|
||||
return redirect()->guest('/login');
|
||||
return redirect()->guest($guard=='client'?'/client/login':'/login');
|
||||
}
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
|
||||
protected function getInvitation($key){
|
||||
$invitation = Invitation::where('invitation_key', '=', $key)->first();
|
||||
if ($invitation && !$invitation->is_deleted) {
|
||||
return $invitation;
|
||||
}
|
||||
else return null;
|
||||
}
|
||||
|
||||
protected function getInvitationContactId($key){
|
||||
$invitation = $this->getInvitation($key);
|
||||
|
||||
return $invitation?$invitation->contact_id:null;
|
||||
}
|
||||
|
||||
protected function getInvitationAccountId($key){
|
||||
$invitation = $this->getInvitation($key);
|
||||
|
||||
return $invitation?$invitation->account_id:null;
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ Route::get('/keep_alive', 'HomeController@keepAlive');
|
||||
Route::post('/get_started', 'AccountController@getStarted');
|
||||
|
||||
// Client visible pages
|
||||
Route::group(['middleware' => 'auth'], function() {
|
||||
Route::group(['middleware' => 'auth:client'], function() {
|
||||
Route::get('view/{invitation_key}', 'PublicClientController@view');
|
||||
Route::get('download/{invitation_key}', 'PublicClientController@download');
|
||||
Route::get('view', 'HomeController@viewLogo');
|
||||
@ -78,6 +78,15 @@ Route::get('/password/reset/{token}', array('as' => 'forgot', 'uses' => 'Auth\Pa
|
||||
Route::post('/password/reset', array('as' => 'forgot', 'uses' => 'Auth\PasswordController@postReset'));
|
||||
Route::get('/user/confirm/{code}', 'UserController@confirm');
|
||||
|
||||
// Client auth
|
||||
Route::get('/client/login', array('as' => 'login', 'uses' => 'ClientAuth\AuthController@getLogin'));
|
||||
Route::post('/client/login', array('as' => 'login', 'uses' => 'ClientAuth\AuthController@postLogin'));
|
||||
Route::get('/client/logout', array('as' => 'logout', 'uses' => 'ClientAuth\AuthController@getLogout'));
|
||||
Route::get('/client/forgot', array('as' => 'forgot', 'uses' => 'ClientAuth\PasswordController@getEmail'));
|
||||
Route::post('/client/forgot', array('as' => 'forgot', 'uses' => 'ClientAuth\PasswordController@postEmail'));
|
||||
Route::get('/client/password/reset/{invitation_key}/{token}', array('as' => 'forgot', 'uses' => 'ClientAuth\PasswordController@getReset'));
|
||||
Route::post('/client/password/reset', array('as' => 'forgot', 'uses' => 'ClientAuth\PasswordController@postReset'));
|
||||
|
||||
|
||||
if (Utils::isNinja()) {
|
||||
Route::post('/signup/register', 'AccountController@doRegister');
|
||||
@ -89,7 +98,7 @@ if (Utils::isReseller()) {
|
||||
Route::post('/reseller_stats', 'AppController@stats');
|
||||
}
|
||||
|
||||
Route::group(['middleware' => 'auth'], function() {
|
||||
Route::group(['middleware' => 'auth:user'], function() {
|
||||
Route::get('dashboard', 'DashboardController@index');
|
||||
Route::get('view_archive/{entity_type}/{visible}', 'AccountController@setTrashVisible');
|
||||
Route::get('hide_message', 'HomeController@hideMessage');
|
||||
@ -685,4 +694,4 @@ if (Utils::isNinjaDev())
|
||||
//ini_set('memory_limit','1024M');
|
||||
//Auth::loginUsingId(1);
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
@ -1,46 +0,0 @@
|
||||
<?php namespace App\Auth;
|
||||
|
||||
use Illuminate\Auth\AuthServiceProvider;
|
||||
use App\Auth\CustomerAuthManager;
|
||||
use App\Auth\SiteGuard;
|
||||
|
||||
class CustomerAuthServiceProvider extends AuthServiceProvider
|
||||
{
|
||||
public function register()
|
||||
{
|
||||
$this->app->alias('customerauth', 'App\Auth\CustomerAuthManager');
|
||||
$this->app->alias('customerauth.driver', 'App\Auth\SiteGuard');
|
||||
$this->app->alias('customerauth.driver', 'App\Contracts\Auth\SiteGuard');
|
||||
|
||||
parent::register();
|
||||
}
|
||||
|
||||
protected function registerAuthenticator()
|
||||
{
|
||||
$this->app->singleton('customerauth', function ($app) {
|
||||
$app['customerauth.loaded'] = true;
|
||||
|
||||
return new CustomerAuthManager($app);
|
||||
});
|
||||
|
||||
$this->app->singleton('customerauth.driver', function ($app) {
|
||||
return $app['customerauth']->driver();
|
||||
});
|
||||
}
|
||||
|
||||
protected function registerUserResolver()
|
||||
{
|
||||
$this->app->bind('Illuminate\Contracts\Auth\Authenticatable', function ($app) {
|
||||
return $app['customerauth']->user();
|
||||
});
|
||||
}
|
||||
|
||||
protected function registerRequestRebindHandler()
|
||||
{
|
||||
$this->app->rebinding('request', function ($app, $request) {
|
||||
$request->setUserResolver(function() use ($app) {
|
||||
return $app['customerauth']->user();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ return [
|
||||
*/
|
||||
|
||||
'defaults' => [
|
||||
'guard' => 'web',
|
||||
'guard' => 'user',
|
||||
'passwords' => 'users',
|
||||
],
|
||||
|
||||
@ -35,10 +35,15 @@ return [
|
||||
*/
|
||||
|
||||
'guards' => [
|
||||
'web' => [
|
||||
'user' => [
|
||||
'driver' => 'session',
|
||||
'provider' => 'users',
|
||||
],
|
||||
|
||||
'client' => [
|
||||
'driver' => 'session',
|
||||
'provider' => 'client',
|
||||
],
|
||||
|
||||
'api' => [
|
||||
'driver' => 'token',
|
||||
@ -68,11 +73,11 @@ return [
|
||||
'driver' => 'eloquent',
|
||||
'model' => App\Models\User::class,
|
||||
],
|
||||
|
||||
// 'users' => [
|
||||
// 'driver' => 'database',
|
||||
// 'table' => 'users',
|
||||
// ],
|
||||
|
||||
'client' => [
|
||||
'driver' => 'eloquent',
|
||||
'model' => App\Models\Contact::class,
|
||||
]
|
||||
],
|
||||
|
||||
/*
|
||||
@ -97,7 +102,13 @@ return [
|
||||
'passwords' => [
|
||||
'users' => [
|
||||
'provider' => 'users',
|
||||
'email' => 'emails.password', //auth.emails.password
|
||||
'email' => 'emails.password',
|
||||
'table' => 'password_resets',
|
||||
'expire' => 60,
|
||||
],
|
||||
'client' => [
|
||||
'provider' => 'client',
|
||||
'email' => 'emails.client_password',
|
||||
'table' => 'password_resets',
|
||||
'expire' => 60,
|
||||
],
|
||||
|
@ -32,6 +32,9 @@
|
||||
{!! Former::text('last_name')->data_bind("value: last_name, valueUpdate: 'afterkeydown'") !!}
|
||||
{!! Former::text('email')->data_bind("value: email, valueUpdate: 'afterkeydown'") !!}
|
||||
{!! Former::text('phone')->data_bind("value: phone, valueUpdate: 'afterkeydown'") !!}
|
||||
@if ($account->isPro() && $account->enable_portal_password)
|
||||
{!! Former::password('password')->data_bind("value: password()?'-%unchanged%-':'', valueUpdate: 'afterkeydown'") !!}
|
||||
@endif
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-lg-8 col-lg-offset-4">
|
||||
|
116
resources/views/clientauth/login.blade.php
Normal file
116
resources/views/clientauth/login.blade.php
Normal file
@ -0,0 +1,116 @@
|
||||
@extends('master')
|
||||
|
||||
@section('head')
|
||||
|
||||
<link href="{{ asset('css/bootstrap.min.css') }}" rel="stylesheet" type="text/css"/>
|
||||
<link href="{{ asset('css/style.css') }}" rel="stylesheet" type="text/css"/>
|
||||
|
||||
<style type="text/css">
|
||||
body {
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
.modal-header {
|
||||
border-top-left-radius: 3px;
|
||||
border-top-right-radius: 3px;
|
||||
}
|
||||
.modal-header h4 {
|
||||
margin:0;
|
||||
}
|
||||
.modal-header img {
|
||||
float: left;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.form-signin {
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
}
|
||||
p.link a {
|
||||
font-size: 11px;
|
||||
}
|
||||
.form-signin .inner {
|
||||
padding: 20px;
|
||||
border-bottom-right-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
border-left: 1px solid #ddd;
|
||||
border-right: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
.form-signin .checkbox {
|
||||
font-weight: normal;
|
||||
}
|
||||
.form-signin .form-control {
|
||||
margin-bottom: 17px !important;
|
||||
}
|
||||
.form-signin .form-control:focus {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.modal-header a:link,
|
||||
.modal-header a:visited,
|
||||
.modal-header a:hover,
|
||||
.modal-header a:active {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('body')
|
||||
<div class="container">
|
||||
|
||||
@include('partials.warn_session', ['redirectTo' => '/client/login'])
|
||||
|
||||
{!! Former::open('client/login')
|
||||
->rules(['password' => 'required'])
|
||||
->addClass('form-signin') !!}
|
||||
{{ Former::populateField('remember', 'true') }}
|
||||
|
||||
<div class="modal-header">
|
||||
<a href="{{ NINJA_WEB_URL }}" target="_blank">
|
||||
<h4>{{ trans('texts.account_login') }}</h4>
|
||||
</a>
|
||||
</div>
|
||||
<div class="inner">
|
||||
<p>
|
||||
{!! Former::password('password')->placeholder(trans('texts.password'))->raw() !!}
|
||||
{!! Former::hidden('remember')->raw() !!}
|
||||
</p>
|
||||
|
||||
<p>{!! Button::success(trans('texts.login'))
|
||||
->withAttributes(['id' => 'loginButton'])
|
||||
->large()->submit()->block() !!}</p>
|
||||
|
||||
<p class="link">
|
||||
{!! link_to('/client/forgot', trans('texts.forgot_password')) !!}
|
||||
</p>
|
||||
|
||||
|
||||
@if (count($errors->all()))
|
||||
<div class="alert alert-danger">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('warning'))
|
||||
<div class="alert alert-warning">{{ Session::get('warning') }}</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('message'))
|
||||
<div class="alert alert-info">{{ Session::get('message') }}</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('error'))
|
||||
<div class="alert alert-danger"><li>{{ Session::get('error') }}</li></div>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
{!! Former::close() !!}
|
||||
</div>
|
||||
@endsection
|
101
resources/views/clientauth/password.blade.php
Normal file
101
resources/views/clientauth/password.blade.php
Normal file
@ -0,0 +1,101 @@
|
||||
@extends('master')
|
||||
|
||||
@section('head')
|
||||
|
||||
<link href="{{ asset('css/bootstrap.min.css') }}" rel="stylesheet" type="text/css"/>
|
||||
<link href="{{ asset('css/style.css') }}" rel="stylesheet" type="text/css"/>
|
||||
|
||||
<style type="text/css">
|
||||
body {
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
.modal-header {
|
||||
border-top-left-radius: 3px;
|
||||
border-top-right-radius: 3px;
|
||||
}
|
||||
.modal-header h4 {
|
||||
margin:0;
|
||||
}
|
||||
.modal-header img {
|
||||
float: left;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.form-signin {
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
}
|
||||
p.link a {
|
||||
font-size: 11px;
|
||||
}
|
||||
.form-signin .inner {
|
||||
padding: 20px;
|
||||
border-bottom-right-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
border-left: 1px solid #ddd;
|
||||
border-right: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
.form-signin .checkbox {
|
||||
font-weight: normal;
|
||||
}
|
||||
.form-signin .form-control {
|
||||
margin-bottom: 17px !important;
|
||||
}
|
||||
.form-signin .form-control:focus {
|
||||
z-index: 2;
|
||||
}
|
||||
</style>
|
||||
|
||||
@stop
|
||||
|
||||
@section('body')
|
||||
<div class="container">
|
||||
|
||||
{!! Former::open('client/forgot')->addClass('form-signin') !!}
|
||||
<div class="modal-header">
|
||||
<h4>{{ trans('texts.password_recovery') }}</h4></div>
|
||||
<div class="inner">
|
||||
|
||||
<p>{!! Button::success(trans('texts.send_email'))->large()->submit()->block() !!}</p>
|
||||
|
||||
@if (count($errors->all()))
|
||||
<div class="alert alert-danger">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (session('status'))
|
||||
<div class="alert alert-info">
|
||||
{{ session('status') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- if there are login errors, show them here -->
|
||||
@if (Session::has('warning'))
|
||||
<div class="alert alert-warning">{{ Session::get('warning') }}</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('message'))
|
||||
<div class="alert alert-info">{{ Session::get('message') }}</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('error'))
|
||||
<div class="alert alert-danger">{{ Session::get('error') }}</div>
|
||||
@endif
|
||||
|
||||
{!! Former::close() !!}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() {
|
||||
$('#email').focus();
|
||||
})
|
||||
</script>
|
||||
|
||||
@stop
|
104
resources/views/clientauth/reset.blade.php
Normal file
104
resources/views/clientauth/reset.blade.php
Normal file
@ -0,0 +1,104 @@
|
||||
@extends('master')
|
||||
|
||||
@section('head')
|
||||
|
||||
<link href="{{ asset('css/bootstrap.min.css') }}" rel="stylesheet" type="text/css"/>
|
||||
<link href="{{ asset('css/style.css') }}" rel="stylesheet" type="text/css"/>
|
||||
|
||||
<style type="text/css">
|
||||
body {
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
.modal-header {
|
||||
border-top-left-radius: 3px;
|
||||
border-top-right-radius: 3px;
|
||||
}
|
||||
.modal-header h4 {
|
||||
margin:0;
|
||||
}
|
||||
.modal-header img {
|
||||
float: left;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.form-signin {
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
}
|
||||
p.link a {
|
||||
font-size: 11px;
|
||||
}
|
||||
.form-signin .inner {
|
||||
padding: 20px;
|
||||
border-bottom-right-radius: 3px;
|
||||
border-bottom-left-radius: 3px;
|
||||
border-left: 1px solid #ddd;
|
||||
border-right: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
.form-signin .checkbox {
|
||||
font-weight: normal;
|
||||
}
|
||||
.form-signin .form-control {
|
||||
margin-bottom: 17px !important;
|
||||
}
|
||||
.form-signin .form-control:focus {
|
||||
z-index: 2;
|
||||
}
|
||||
</style>
|
||||
|
||||
@stop
|
||||
|
||||
@section('body')
|
||||
<div class="container">
|
||||
|
||||
{!! Former::open('/client/password/reset')->addClass('form-signin')->rules(array(
|
||||
'password' => 'required',
|
||||
'password_confirmation' => 'required',
|
||||
)) !!}
|
||||
|
||||
<div class="modal-header">
|
||||
<h4>{{ trans('texts.set_password') }}</h4></div>
|
||||
<div class="inner">
|
||||
|
||||
<input type="hidden" name="token" value="{{{ $token }}}">
|
||||
<input type="hidden" name="invitation_key" value="{{{ $invitation_key }}}">
|
||||
|
||||
<p>
|
||||
{!! Former::password('password')->placeholder(trans('texts.password'))->raw() !!}
|
||||
{!! Former::password('password_confirmation')->placeholder(trans('texts.confirm_password'))->raw() !!}
|
||||
|
||||
</p>
|
||||
|
||||
<p>{!! Button::success(trans('texts.save'))->large()->submit()->block() !!}</p>
|
||||
|
||||
|
||||
@if (count($errors->all()))
|
||||
<div class="alert alert-danger">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- if there are login errors, show them here -->
|
||||
@if (Session::has('warning'))
|
||||
<div class="alert alert-warning">{{ Session::get('warning') }}</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('message'))
|
||||
<div class="alert alert-info">{{ Session::get('message') }}</div>
|
||||
@endif
|
||||
|
||||
@if (Session::has('error'))
|
||||
<div class="alert alert-danger">{{ Session::get('error') }}</div>
|
||||
@endif
|
||||
|
||||
|
||||
{!! Former::close() !!}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@stop
|
@ -93,7 +93,7 @@
|
||||
attr: {name: 'contacts[' + \$index() + '][email]', id:'email'+\$index()}") !!}
|
||||
{!! Former::text('phone')->data_bind("value: phone, valueUpdate: 'afterkeydown',
|
||||
attr: {name: 'contacts[' + \$index() + '][phone]'}") !!}
|
||||
@if (!Utils::isPro() || $account->enable_portal_password)
|
||||
@if ($account->isPro() && $account->enable_portal_password)
|
||||
{!! Former::password('password')->data_bind("value: password()?'-%unchanged%-':'', valueUpdate: 'afterkeydown',
|
||||
attr: {name: 'contacts[' + \$index() + '][password]'}") !!}
|
||||
@endif
|
||||
|
26
resources/views/emails/client_password.blade.php
Normal file
26
resources/views/emails/client_password.blade.php
Normal file
@ -0,0 +1,26 @@
|
||||
@extends('emails.master_user')
|
||||
|
||||
@section('body')
|
||||
<div>
|
||||
{{ trans('texts.reset_password') }}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<center>
|
||||
@include('partials.email_button', [
|
||||
'link' => URL::to("client/password/reset/".session('invitation_key')."/{$token}"),
|
||||
'field' => 'reset',
|
||||
'color' => '#36c157',
|
||||
])
|
||||
</center>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{{ trans('texts.email_signature') }}<br/>
|
||||
{{ trans('texts.email_from') }}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{{ trans('texts.reset_password_footer') }}
|
||||
</div>
|
||||
@stop
|
@ -543,7 +543,10 @@
|
||||
->addClass('client-email') !!}
|
||||
{!! Former::text('phone')->data_bind("value: phone, valueUpdate: 'afterkeydown',
|
||||
attr: {name: 'client[contacts][' + \$index() + '][phone]'}") !!}
|
||||
f
|
||||
@if ($account->isPro() && $account->enable_portal_password)
|
||||
{!! Former::password('password')->data_bind("value: (typeof password=='function'?password():null)?'-%unchanged%-':'', valueUpdate: 'afterkeydown',
|
||||
attr: {name: 'client[contacts][' + \$index() + '][password]'}") !!}
|
||||
@endif
|
||||
<div class="form-group">
|
||||
<div class="col-lg-8 col-lg-offset-4">
|
||||
<span class="redlink bold" data-bind="visible: $parent.contacts().length > 1">
|
||||
|
Loading…
Reference in New Issue
Block a user