Default skin client auth

This commit is contained in:
David Bomba 2019-07-17 13:09:37 +10:00
parent 4cc9ca2748
commit 99a535eed8
13 changed files with 332 additions and 124 deletions

View File

@ -78,7 +78,7 @@ before_script:
script:
- php ./vendor/bin/phpunit --debug --verbose --coverage-clover=coverage.xml
# php artisan dusk
- npm test
#- npm test
after_success:
- bash <(curl -s https://codecov.io/bash)

View File

@ -31,33 +31,36 @@ class ContactLoginController extends Controller
public function showLoginForm()
{
return view('auth.contact_login');
return view('portal.default.auth.login');
}
public function login(Request $request)
{
Auth::shouldUse('contact');
Auth::shouldUse('contact');
$this->validateLogin($request);
if ($this->hasTooManyLoginAttempts($request)) {
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
if (method_exists($this, 'hasTooManyLoginAttempts') &&
$this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return response()->json(['message' => 'Too many login attempts, you are being throttled']);
return $this->sendLockoutResponse($request);
}
if ($this->attemptLogin($request))
return redirect()->intended(route('client.dashboard'));
else {
$this->incrementLoginAttempts($request);
return redirect()->back()->withInput($request->only('email', 'remember'));
if ($this->attemptLogin($request)) {
return $this->sendLoginResponse($request);
}
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
public function logout()
{

View File

@ -108,7 +108,7 @@ class BaseController extends Controller
public function notFound()
{
return response()->json([
'message' => 'Nothing to see here!'], 404);
'message' => '404 | Nothing to see here!'], 404);
}
public function notFoundClient()

View File

@ -0,0 +1,45 @@
<?php
/**
* Invoice Ninja (https://invoiceninja.com)
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2019. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://opensource.org/licenses/AAL
*/
namespace App\Listeners\Contact;
use App\Models\Activity;
use App\Repositories\ActivityRepository;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class UpdateContactLastLogin
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle($event)
{
$client_contact = $event->client_contact;
$client_contact->last_login = now();
$client_contact->save();
}
}

View File

@ -7,54 +7,20 @@
"watch-poll": "npm run watch -- --watch-poll",
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
"prod": "npm run production",
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
"test": "jest"
},
"devDependencies": {
"@coreui/coreui": "^2.0.12",
"@coreui/coreui-plugin-chartjs-custom-tooltips": "1.2.0",
"@coreui/icons": "^0.3.0",
"@types/bluebird": "^3.5.25",
"@types/core-js": "^0.9.36",
"@types/jest": "^23.3.9",
"axios": "^0.18",
"babel-preset-stage-2": "^6.24.1",
"bootstrap": "^4.0.0",
"chart.js": "^2.7.3",
"cross-env": "^5.1",
"flag-icon-css": "3.2.0",
"font-awesome": "^4.7",
"jest": "^23.6.0",
"jquery": "^3.2",
"laravel-mix": "^2.0",
"pace-progress": "1.0.2",
"perfect-scrollbar": "1.4.0",
"popper.js": "^1.12",
"simple-line-icons": "2.4.1",
"ts-jest": "^23.10.5",
"vue": "^2.5.17",
"vuetable-2": "^1.7.5"
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {},
"dependencies": {
"@types/lodash": "^4.14.118",
"@types/node": "^10.12.10",
"axios-progress-bar": "^1.2.0",
"chalk": "^2.4.2",
"hashids": "^1.2.2",
"laravel-echo": "^1.4.0",
"lodash.get": "^4.4.2",
"puppeteer": "^1.18.1",
"quill": "^1.3.6",
"socket.io-client": "^2.1.1",
"ts-loader": "3.5.0",
"typescript": "^3.1.6",
"vue-affix": "^0.4.0",
"vue-chartjs": "^3.4.0",
"vue-events": "^3.1.0",
"vue-multiselect": "^2.1.3",
"vue-scrollactive": "^0.8.0",
"vue-select": "^2.5.1",
"vue-toastr": "^2.0.16",
"vuex": "^3.1.0"
"@coreui/coreui": "^2.1.12",
"@coreui/icons": "^0.3.0",
"bootstrap": "^4.3.1",
"font-awesome": "^4.7.0",
"laravel-mix": "^4.1.2",
"puppeteer": "^1.18.1"
},
"peerDependencies": {
"jquery": "1.9.1 - 3",
"perfect-scrollbar": "^1.3.0",
"popper.js": "^1.14.3"
}
}

View File

@ -1,17 +1,11 @@
{
"/js/client_list.js": "/js/client_list.js?id=497dadf330d671d77df2",
"/js/client_edit.js": "/js/client_edit.js?id=4af6b4f5e15167bbc24d",
"/js/client_show.js": "/js/client_show.js?id=d1fa3c09614c73dc4b7e",
"/js/client_create.js": "/js/client_create.js?id=d5acb9e9a827386a517c",
"/js/localization.js": "/js/localization.js?id=054592ec61c720b458de",
"/js/coreui.js": "/js/coreui.js?id=3c7e911851224f97523e",
"/js/ninja.min.js": "/js/ninja.min.js?id=d41d8cd98f00b204e980",
"/js/coreui.min.js": "/js/coreui.min.js?id=3c7e911851224f97523e",
"/js/client_show.min.js": "/js/client_show.min.js?id=d1fa3c09614c73dc4b7e",
"/js/client_edit.min.js": "/js/client_edit.min.js?id=4af6b4f5e15167bbc24d",
"/js/client_create.min.js": "/js/client_create.min.js?id=d5acb9e9a827386a517c",
"/js/client_list.min.js": "/js/client_list.min.js?id=497dadf330d671d77df2",
"/js/localization.min.js": "/js/localization.min.js?id=054592ec61c720b458de",
"/css/ninja.css": "/css/ninja.css?id=28421bc494c5086ac359",
"/css/ninja.min.css": "/css/ninja.min.css?id=28421bc494c5086ac359"
"/vendors/css/coreui.min.css": "/vendors/css/coreui.min.css?id=cc8e626c1902d53ee805",
"/vendors/css/coreui-icons.min.css": "/vendors/css/coreui-icons.min.css?id=23447e24a210c12e4559",
"/vendors/css/bootstrap.min.css": "/vendors/css/bootstrap.min.css?id=6f27def50398084c3b22",
"/vendors/css/font-awesome.min.css": "/vendors/css/font-awesome.min.css?id=269550530cc127b6aa5a",
"/vendors/js/coreui.min.js": "/vendors/js/coreui.min.js?id=0fa9ac379e62c48d26e6",
"/vendors/js/bootstrap.min.js": "/vendors/js/bootstrap.min.js?id=e1d98d47689e00f8ecbc",
"/vendors/js/jquery.min.js": "/vendors/js/jquery.min.js?id=220afd743d9e9643852e",
"/vendors/js/popper.min.js": "/vendors/js/popper.min.js?id=61b9b07b83557d9325c3",
"/vendors/js/perfect-scrollbar.min.js": "/vendors/js/perfect-scrollbar.min.js?id=4a10bcfa0a9c9fa9d503"
}

View File

@ -0,0 +1,103 @@
@extends('portal.default.layouts.guest')
@section('body')
<body class="app flex-row align-items-center">
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card-group">
<div class="card p-4">
<div class="card-body">
@if (session('info'))
<div class="row">
<div class="col-md-12">
<div class="alert alert-success alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
{{ session('info') }}
</div>
</div>
</div>
@elseif (session('error'))
<div class="row">
<div class="col-md-12">
<div class="alert alert-danger alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
{{ session('error') }}
</div>
</div>
</div>
@endif
<form method="POST" action="{{ route('client.login') }}">
@csrf
<h1>@lang('texts.account_login')</h1>
@if (Session::has('error'))
<div class="alert alert-danger">
<li>{!! Session::get('error') !!}</li>
</div>
@endif
<p class="text-muted"></p>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">
<i class="icon-user"></i>
</span>
</div>
<input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}" placeholder="@lang('texts.email')" required autofocus>
@if ($errors->has('email'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('email') }}</strong>
</span>
@endif
</div>
<div class="input-group mb-4">
<div class="input-group-prepend">
<span class="input-group-text">
<i class="icon-lock"></i>
</span>
</div>
<input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" placeholder="@lang('texts.password')" required>
@if ($errors->has('password'))
<span class="invalid-feedback" role="alert">
<strong>{{ $errors->first('password') }}</strong>
</span>
@endif
</div>
<div class="row">
<div class="col-6">
<button class="btn btn-primary px-4" type="submit">@lang('texts.login')</button>
</div>
<div class="col-6 text-right">
<a class="btn btn-link" href="{{ route('password.request') }}">
@lang('texts.forgot_password')
</a>
</div>
</div>
</form>
</div>
</div>
@env('hosted')
<!--<div class="card text-white bg-primary py-5 d-md-down-none" style="width:44%">
<div class="card-body text-center">
<div>
<h2>@lang('texts.sign_up_now')</h2>
<p>@lang('texts.not_a_member_yet')</p>
<a class="btn btn-primary active mt-3" href="{{route('signup') }}">@lang('texts.login_create_an_account')</a>
</div>
</div>
</div>
-->
@endenv
</div>
</div>
</div>
</div>
</body>
@endsection

View File

@ -0,0 +1,15 @@
<footer class="app-footer">
<div class="ml-auto">
<span>Powered by</span>
<a href="https://invoiceninja.com">InvoiceNinja</a> &copy; 2018 Invoice Ninja LLC.
</div>
</footer>
<!-- Bootstrap and necessary plugins-->
<script src="/vendors/js/jquery.min.js"></script>
<script src="/vendors/js/popper.min.js"></script>
<script src="/vendors/js/bootstrap.min.js"></script>
<script src="/vendors/js/perfect-scrollbar.min.js"></script>
<script src="/vendors/coreui.min.js"></script>
<script>
$('#ui-view').ajaxLoad();
</script>

View File

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<!-- Source: https://github.com/invoiceninja/invoiceninja -->
<!-- Error: {{ session('error') }} -->
@if (config('services.analytics.tracking_id'))
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-122229484-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{{ config('services.analytics.tracking_id') }}', { 'anonymize_ip': true });
function trackEvent(category, action) {
ga('send', 'event', category, action, this.src);
}
</script>
<script>
Vue.config.devtools = true;
</script>
@else
<script>
function gtag(){}
</script>
@endif
<meta charset="utf-8">
<title>@yield('meta_title', 'Invoice Ninja') | {{ config('app.name') }}</title>
<meta name="description" content="@yield('meta_description')"/>
<link href="{{ asset('favicon.png') }}" rel="shortcut icon" type="image/png">
<base href="./">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<meta name="author" content="Łukasz Holeczek">
<meta name="keyword" content="Bootstrap,Admin,Template,Open,Source,jQuery,CSS,HTML,RWD,Dashboard">
<!-- Icons-->
<link href="/vendors/css/coreui-icons.min.css" rel="stylesheet">
<link href="/vendors/css/font-awesome.min.css" rel="stylesheet">
<!-- Main styles for this application-->
<link href="/vendors/css/bootstrap.min.css" rel="stylesheet">
<link href="/vendors/css/coreui.min.css" rel="stylesheet">
@yield('head')
</head>
@include('portal.default.header', $header)
@yield('header')
@include('portal.default.sidebar')
@yield('sidebar')
@section('body')
@yield('body')
</html>

View File

@ -0,0 +1,59 @@
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<!-- Source: https://github.com/invoiceninja/invoiceninja -->
<!-- Error: {{ session('error') }} -->
@if (config('services.analytics.tracking_id'))
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-122229484-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{{ config('services.analytics.tracking_id') }}', { 'anonymize_ip': true });
function trackEvent(category, action) {
ga('send', 'event', category, action, this.src);
}
</script>
<script>
Vue.config.devtools = true;
</script>
@else
<script>
function gtag(){}
</script>
@endif
<meta charset="utf-8">
<title>@yield('meta_title', 'Invoice Ninja') | {{ config('app.name') }}</title>
<meta name="description" content="@yield('meta_description')"/>
<link href="{{ asset('favicon.png') }}" rel="shortcut icon" type="image/png">
<base href="./">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<meta name="author" content="Łukasz Holeczek">
<meta name="keyword" content="Bootstrap,Admin,Template,Open,Source,jQuery,CSS,HTML,RWD,Dashboard">
<!-- Icons-->
<link href="/vendors/css/coreui-icons.min.css" rel="stylesheet">
<link href="/vendors/css/font-awesome.min.css" rel="stylesheet">
<!-- Main styles for this application-->
<link href="/vendors/css/bootstrap.min.css" rel="stylesheet">
<link href="/vendors/css/coreui.min.css" rel="stylesheet">
@yield('head')
</head>
@include('portal.default.header', $header)
@yield('header')
@include('portal.default.sidebar')
@yield('sidebar')
@section('body')
@yield('body')
@include('portal.default.footer')
@yield('footer')
</html>

52
webpack.mix.js vendored
View File

@ -11,50 +11,16 @@ const mix = require('laravel-mix');
|
*/
mix.webpackConfig({
resolve: {
extensions: ['.ts']
},
module: {
rules: [
{
test: /\.ts$/,
loader: 'ts-loader',
options: { appendTsSuffixTo: [/\.vue$/] },
exclude: /node_modules/,
}
]
}
});
mix.js('resources/js/src/client/client_show.ts', 'public/js');
mix.js('resources/js/src/client/client_edit.ts', 'public/js');
mix.js('resources/js/src/client/client_create.ts', 'public/js');
mix.js('resources/js/src/client/client_list.ts', 'public/js');
mix.js('resources/js/src/settings/localization.ts', 'public/js');
mix.js('node_modules/@coreui/coreui/dist/js/coreui.js', 'public/js');
/*
mix.scripts([
'js/src/bootstrap.js'
], 'public/js/ninja.js');
*/
mix.minify('public/js/ninja.js');
mix.minify('public/js/coreui.js');
mix.minify('public/js/client_show.js');
mix.minify('public/js/client_edit.js');
mix.minify('public/js/client_create.js');
mix.minify('public/js/client_list.js');
mix.minify('public/js/localization.js');
mix.styles([
'node_modules/@coreui/coreui/dist/css/coreui.css',
'node_modules/@coreui/icons/css/coreui-icons.css',
'node_modules/font-awesome/css/font-awesome.css'
], 'public/css/ninja.css');
mix.minify('public/css/ninja.css');
mix.copyDirectory('node_modules/@coreui/coreui/dist/css/coreui.min.css', 'public/vendors/css/coreui.min.css');
mix.copyDirectory('node_modules/@coreui/icons/css/coreui-icons.min.css', 'public/vendors/css/coreui-icons.min.css');
mix.copyDirectory('node_modules/@coreui/coreui/dist/css/bootstrap.min.css', 'public/vendors/css/bootstrap.min.css');
mix.copyDirectory('node_modules/font-awesome/css/font-awesome.min.css', 'public/vendors/css/font-awesome.min.css');
mix.copyDirectory('node_modules/@coreui/coreui/dist/js/coreui.min.js', 'public/vendors/js/coreui.min.js');
mix.copyDirectory('node_modules/bootstrap/dist/js/bootstrap.min.js', 'public/vendors/js/bootstrap.min.js');
mix.copyDirectory('node_modules/jquery/dist/jquery.min.js', 'public/vendors/js/jquery.min.js');
mix.copyDirectory('node_modules/popper.js/dist/popper.min.js', 'public/vendors/js/popper.min.js');
mix.copyDirectory('node_modules/perfect-scrollbar/dist/perfect-scrollbar.min.js', 'public/vendors/js/perfect-scrollbar.min.js');
mix.copyDirectory('node_modules/font-awesome/fonts', 'public/fonts');