implemented social identities management page + pw editing page. probably need to fix backend

pull/26/head
Ondřej Hruška 6 years ago
parent 57911377ef
commit 2e075799f2
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 17
      app/Http/Controllers/Auth/LoginController.php
  2. 19
      app/Http/Controllers/ProfileController.php
  3. 2
      app/Http/Middleware/RedirectIfAuthenticated.php
  4. 3
      app/Providers/AppServiceProvider.php
  5. 7
      app/View/WidgetFactory.php
  6. 4
      database/migrations/2018_07_08_204449_create_oauth_identities_table.php
  7. 194
      public/fonts/fa-dtbl-1-preview.html
  8. 89
      public/fonts/fa-dtbl-1.css
  9. BIN
      public/fonts/fa-dtbl-1.eot
  10. 99
      public/fonts/fa-dtbl-1.svg
  11. BIN
      public/fonts/fa-dtbl-1.ttf
  12. BIN
      public/fonts/fa-dtbl-1.woff2
  13. 4
      resources/assets/sass/_fa-utils.scss
  14. 8
      resources/assets/sass/_helpers.scss
  15. 2
      resources/views/auth/login.blade.php
  16. 2
      resources/views/form/checkbox.blade.php
  17. 36
      resources/views/layouts/main-nav.blade.php
  18. 27
      resources/views/layouts/nav-buttons.blade.php
  19. 0
      resources/views/profile/_table-list.blade.php
  20. 33
      resources/views/profile/edit.blade.php
  21. 140
      resources/views/profile/logins.blade.php
  22. 4
      resources/views/profile/view.blade.php
  23. 49
      resources/views/user/edit.blade.php
  24. 15
      resources/views/user/logins.blade.php
  25. 25
      routes/login.php
  26. 12
      routes/web.php
  27. 4
      sideload/adamwathan/eloquent-oauth/src/Authenticator.php
  28. 6
      sideload/adamwathan/eloquent-oauth/src/OAuthIdentity.php
  29. 5
      sideload/socialnorm/facebook/src/FacebookProvider.php
  30. 5
      sideload/socialnorm/github/src/GitHubProvider.php
  31. 5
      sideload/socialnorm/google/src/GoogleProvider.php
  32. 3
      sideload/socialnorm/socialnorm/src/ProviderUser.php
  33. 3
      sideload/socialnorm/socialnorm/src/Providers/OAuth2Provider.php
  34. 5
      sideload/socialnorm/stackoverflow/src/StackOverflowProvider.php
  35. 11
      vendor_patches/20_ci_login.patch

@ -4,6 +4,8 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
class LoginController extends Controller
{
@ -36,4 +38,19 @@ class LoginController extends Controller
{
$this->middleware('guest')->except('logout');
}
public function username()
{
$login = request()->input('login');
$field = filter_var($login, FILTER_VALIDATE_EMAIL) ? 'email' : 'name';
request()->merge([$field => $login]);
return $field;
}
protected function sendFailedLoginResponse(Request $request)
{
throw ValidationException::withMessages([
'login' => [trans('auth.failed')],
]);
}
}

@ -10,7 +10,7 @@ use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use MightyPork\Utils\Str;
class UserController extends Controller
class ProfileController extends Controller
{
/**
* Show the application dashboard.
@ -23,7 +23,7 @@ class UserController extends Controller
->with('revision:id,row_count')
->paginate(10);
return view('user.view')->with(compact('tables', 'user'));
return view('profile.view')->with(compact('tables', 'user'));
}
/**
@ -34,7 +34,7 @@ class UserController extends Controller
*/
public function edit()
{
return view('user.edit')->with('user', \user());
return view('profile.edit')->with('user', \user());
}
/**
@ -92,6 +92,17 @@ class UserController extends Controller
public function manageOauth()
{
return view('user.logins', ['user' => user()]);
return view('profile.logins', ['user' => user()]);
}
public function forgetSocialLogin($id)
{
$identity = user()->socialIdentities()->where('id', $id)->first();
if (null === $identity) {
abort(404, "No such identity");
}
$identity->delete();
return redirect(route('profile.manage-oauth'));
}
}

@ -18,7 +18,7 @@ class RedirectIfAuthenticated
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/home');
return redirect('/');
}
return $next($request);

@ -20,7 +20,8 @@ class AppServiceProvider extends ServiceProvider
}
\Route::bind('user', function ($value) {
$u = User::where('name', $value)->first();
// Hack to have the URL case insensitive (also needed a vendor patch for login)
$u = User::whereRaw('LOWER(name)=LOWER(?)', [$value])->first();
// it may also be the _id directly
if (!$u && is_numeric($value)) $u = User::find((int)$value);
if (!$u) abort(404);

@ -21,10 +21,11 @@ class WidgetFactory
"</div>";
}
public function par($text)
public function par($text, $extraClasses='')
{
return "<div class=\"row\">".
"<p class=\"col-md-$this->fieldCols offset-md-$this->labelCols\">".e($text)."</o>".
return
"<div class=\"row\">".
"<p class=\"col-md-$this->fieldCols offset-md-$this->labelCols mb-2 ".e($extraClasses)."\">".e($text)."</o>".
"</div>";
}

@ -20,6 +20,10 @@ class CreateOauthIdentitiesTable extends Migration
$table->string('provider_user_id');
$table->string('provider');
$table->string('access_token');
$table->string('nick_name');
$table->string('full_name');
$table->string('avatar', 500);
$table->string('email');
$table->foreign('user_id')
->references('id')->on('users')

@ -161,6 +161,7 @@
[data-icon]:before { content: attr(data-icon); }
[data-icon]:before,
.fa-address-card-o:before,
.fa-at:before,
.fa-bell:before,
.fa-bell-o:before,
@ -219,50 +220,51 @@
font-smoothing: antialiased;
}
.fa-at:before { content: "\f100"; }
.fa-bell:before { content: "\f101"; }
.fa-bell-o:before { content: "\f102"; }
.fa-calendar:before { content: "\f103"; }
.fa-check:before { content: "\f104"; }
.fa-clock-o:before { content: "\f105"; }
.fa-cloud-upload:before { content: "\f106"; }
.fa-code-fork:before { content: "\f107"; }
.fa-download:before { content: "\f108"; }
.fa-eye:before { content: "\f109"; }
.fa-eye-slash:before { content: "\f10a"; }
.fa-facebook-square:before { content: "\f10b"; }
.fa-filter:before { content: "\f10c"; }
.fa-flag:before { content: "\f10d"; }
.fa-floppy-o:before { content: "\f10e"; }
.fa-gavel:before { content: "\f10f"; }
.fa-github:before { content: "\f110"; }
.fa-globe:before { content: "\f111"; }
.fa-google:before { content: "\f112"; }
.fa-history:before { content: "\f113"; }
.fa-key-modern:before { content: "\f114"; }
.fa-link:before { content: "\f115"; }
.fa-pencil-square-o:before { content: "\f116"; }
.fa-question-circle:before { content: "\f117"; }
.fa-quote-left:before { content: "\f118"; }
.fa-reply:before { content: "\f119"; }
.fa-rss:before { content: "\f11a"; }
.fa-search:before { content: "\f11b"; }
.fa-share-alt:before { content: "\f11c"; }
.fa-sign-in:before { content: "\f11d"; }
.fa-sign-out:before { content: "\f11e"; }
.fa-sliders:before { content: "\f11f"; }
.fa-sort:before { content: "\f120"; }
.fa-sort-asc:before { content: "\f121"; }
.fa-sort-desc:before { content: "\f122"; }
.fa-star:before { content: "\f123"; }
.fa-star-o:before { content: "\f124"; }
.fa-table:before { content: "\f125"; }
.fa-times:before { content: "\f126"; }
.fa-trash:before { content: "\f127"; }
.fa-trash-o:before { content: "\f128"; }
.fa-user-circle-o:before { content: "\f129"; }
.fa-user-plus:before { content: "\f12a"; }
.fa-wrench:before { content: "\f12b"; }
.fa-address-card-o:before { content: "\f100"; }
.fa-at:before { content: "\f101"; }
.fa-bell:before { content: "\f102"; }
.fa-bell-o:before { content: "\f103"; }
.fa-calendar:before { content: "\f104"; }
.fa-check:before { content: "\f105"; }
.fa-clock-o:before { content: "\f106"; }
.fa-cloud-upload:before { content: "\f107"; }
.fa-code-fork:before { content: "\f108"; }
.fa-download:before { content: "\f109"; }
.fa-eye:before { content: "\f10a"; }
.fa-eye-slash:before { content: "\f10b"; }
.fa-facebook-square:before { content: "\f10c"; }
.fa-filter:before { content: "\f10d"; }
.fa-flag:before { content: "\f10e"; }
.fa-floppy-o:before { content: "\f10f"; }
.fa-gavel:before { content: "\f110"; }
.fa-github:before { content: "\f111"; }
.fa-globe:before { content: "\f112"; }
.fa-google:before { content: "\f113"; }
.fa-history:before { content: "\f114"; }
.fa-key-modern:before { content: "\f115"; }
.fa-link:before { content: "\f116"; }
.fa-pencil-square-o:before { content: "\f117"; }
.fa-question-circle:before { content: "\f118"; }
.fa-quote-left:before { content: "\f119"; }
.fa-reply:before { content: "\f11a"; }
.fa-rss:before { content: "\f11b"; }
.fa-search:before { content: "\f11c"; }
.fa-share-alt:before { content: "\f11d"; }
.fa-sign-in:before { content: "\f11e"; }
.fa-sign-out:before { content: "\f11f"; }
.fa-sliders:before { content: "\f120"; }
.fa-sort:before { content: "\f121"; }
.fa-sort-asc:before { content: "\f122"; }
.fa-sort-desc:before { content: "\f123"; }
.fa-star:before { content: "\f124"; }
.fa-star-o:before { content: "\f125"; }
.fa-table:before { content: "\f126"; }
.fa-times:before { content: "\f127"; }
.fa-trash:before { content: "\f128"; }
.fa-trash-o:before { content: "\f129"; }
.fa-user-circle-o:before { content: "\f12a"; }
.fa-user-plus:before { content: "\f12b"; }
.fa-wrench:before { content: "\f12c"; }
</style>
<!--[if lte IE 8]><script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
@ -278,11 +280,25 @@
<body class="characters-off">
<div id="page" class="container">
<header>
<h1>fa-dtbl-1 contains 44 glyphs:</h1>
<h1>fa-dtbl-1 contains 45 glyphs:</h1>
<a onclick="toggleCharacters(); return false;" href="#">Toggle Preview Characters</a>
</header>
<div class="glyph">
<div class="preview-glyphs">
<span class="step size-12"><span class="letters">Pp</span><i id="fa-address-card-o" class="fa-address-card-o"></i></span><span class="step size-14"><span class="letters">Pp</span><i id="fa-address-card-o" class="fa-address-card-o"></i></span><span class="step size-16"><span class="letters">Pp</span><i id="fa-address-card-o" class="fa-address-card-o"></i></span><span class="step size-18"><span class="letters">Pp</span><i id="fa-address-card-o" class="fa-address-card-o"></i></span><span class="step size-21"><span class="letters">Pp</span><i id="fa-address-card-o" class="fa-address-card-o"></i></span><span class="step size-24"><span class="letters">Pp</span><i id="fa-address-card-o" class="fa-address-card-o"></i></span><span class="step size-36"><span class="letters">Pp</span><i id="fa-address-card-o" class="fa-address-card-o"></i></span><span class="step size-48"><span class="letters">Pp</span><i id="fa-address-card-o" class="fa-address-card-o"></i></span><span class="step size-60"><span class="letters">Pp</span><i id="fa-address-card-o" class="fa-address-card-o"></i></span><span class="step size-72"><span class="letters">Pp</span><i id="fa-address-card-o" class="fa-address-card-o"></i></span>
</div>
<div class="preview-scale">
<span class="step">12</span><span class="step">14</span><span class="step">16</span><span class="step">18</span><span class="step">21</span><span class="step">24</span><span class="step">36</span><span class="step">48</span><span class="step">60</span><span class="step">72</span>
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-address-card-o" />
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-vcard-o" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf100;" />
</div>
</div>
<div class="glyph">
<div class="preview-glyphs">
<span class="step size-12"><span class="letters">Pp</span><i id="fa-at" class="fa-at"></i></span><span class="step size-14"><span class="letters">Pp</span><i id="fa-at" class="fa-at"></i></span><span class="step size-16"><span class="letters">Pp</span><i id="fa-at" class="fa-at"></i></span><span class="step size-18"><span class="letters">Pp</span><i id="fa-at" class="fa-at"></i></span><span class="step size-21"><span class="letters">Pp</span><i id="fa-at" class="fa-at"></i></span><span class="step size-24"><span class="letters">Pp</span><i id="fa-at" class="fa-at"></i></span><span class="step size-36"><span class="letters">Pp</span><i id="fa-at" class="fa-at"></i></span><span class="step size-48"><span class="letters">Pp</span><i id="fa-at" class="fa-at"></i></span><span class="step size-60"><span class="letters">Pp</span><i id="fa-at" class="fa-at"></i></span><span class="step size-72"><span class="letters">Pp</span><i id="fa-at" class="fa-at"></i></span>
@ -292,7 +308,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-at" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf100;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf101;" />
</div>
</div>
@ -305,7 +321,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-bell" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf101;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf102;" />
</div>
</div>
@ -318,7 +334,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-bell-o" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf102;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf103;" />
</div>
</div>
@ -331,7 +347,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-calendar" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf103;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf104;" />
</div>
</div>
@ -344,7 +360,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-check" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf104;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf105;" />
</div>
</div>
@ -357,7 +373,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-clock-o" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf105;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf106;" />
</div>
</div>
@ -370,7 +386,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-cloud-upload" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf106;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf107;" />
</div>
</div>
@ -383,7 +399,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-code-fork" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf107;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf108;" />
</div>
</div>
@ -396,7 +412,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-download" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf108;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf109;" />
</div>
</div>
@ -409,7 +425,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-eye" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf109;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf10a;" />
</div>
</div>
@ -422,7 +438,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-eye-slash" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf10a;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf10b;" />
</div>
</div>
@ -435,7 +451,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-facebook-square" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf10b;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf10c;" />
</div>
</div>
@ -448,7 +464,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-filter" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf10c;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf10d;" />
</div>
</div>
@ -461,7 +477,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-flag" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf10d;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf10e;" />
</div>
</div>
@ -475,7 +491,7 @@
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-floppy-o" />
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-save" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf10e;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf10f;" />
</div>
</div>
@ -489,7 +505,7 @@
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-gavel" />
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-legal" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf10f;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf110;" />
</div>
</div>
@ -502,7 +518,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-github" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf110;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf111;" />
</div>
</div>
@ -515,7 +531,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-globe" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf111;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf112;" />
</div>
</div>
@ -528,7 +544,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-google" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf112;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf113;" />
</div>
</div>
@ -541,7 +557,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-history" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf113;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf114;" />
</div>
</div>
@ -554,7 +570,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-key-modern" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf114;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf115;" />
</div>
</div>
@ -567,7 +583,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-link" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf115;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf116;" />
</div>
</div>
@ -581,7 +597,7 @@
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-pencil-square-o" />
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-edit" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf116;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf117;" />
</div>
</div>
@ -594,7 +610,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-question-circle" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf117;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf118;" />
</div>
</div>
@ -607,7 +623,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-quote-left" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf118;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf119;" />
</div>
</div>
@ -620,7 +636,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-reply" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf119;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf11a;" />
</div>
</div>
@ -633,7 +649,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-rss" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf11a;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf11b;" />
</div>
</div>
@ -646,7 +662,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-search" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf11b;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf11c;" />
</div>
</div>
@ -659,7 +675,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-share-alt" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf11c;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf11d;" />
</div>
</div>
@ -672,7 +688,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-sign-in" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf11d;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf11e;" />
</div>
</div>
@ -685,7 +701,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-sign-out" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf11e;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf11f;" />
</div>
</div>
@ -698,7 +714,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-sliders" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf11f;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf120;" />
</div>
</div>
@ -711,7 +727,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-sort" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf120;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf121;" />
</div>
</div>
@ -724,7 +740,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-sort-asc" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf121;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf122;" />
</div>
</div>
@ -737,7 +753,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-sort-desc" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf122;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf123;" />
</div>
</div>
@ -750,7 +766,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-star" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf123;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf124;" />
</div>
</div>
@ -763,7 +779,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-star-o" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf124;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf125;" />
</div>
</div>
@ -776,7 +792,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-table" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf125;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf126;" />
</div>
</div>
@ -790,7 +806,7 @@
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-times" />
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-close" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf126;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf127;" />
</div>
</div>
@ -803,7 +819,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-trash" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf127;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf128;" />
</div>
</div>
@ -816,7 +832,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-trash-o" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf128;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf129;" />
</div>
</div>
@ -829,7 +845,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-user-circle-o" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf129;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf12a;" />
</div>
</div>
@ -842,7 +858,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-user-plus" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf12a;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf12b;" />
</div>
</div>
@ -855,7 +871,7 @@
</div>
<div class="usage">
<input class="class" type="text" readonly="readonly" onClick="this.select();" value=".fa-wrench" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf12b;" />
<input class="point" type="text" readonly="readonly" onClick="this.select();" value="&amp;#xf12c;" />
</div>
</div>

@ -38,47 +38,48 @@
font-smoothing: antialiased;
}
.fa-at::before { content: "\f100"; }
.fa-bell::before { content: "\f101"; }
.fa-bell-o::before { content: "\f102"; }
.fa-calendar::before { content: "\f103"; }
.fa-check::before { content: "\f104"; }
.fa-clock-o::before { content: "\f105"; }
.fa-cloud-upload::before { content: "\f106"; }
.fa-code-fork::before { content: "\f107"; }
.fa-download::before { content: "\f108"; }
.fa-eye::before { content: "\f109"; }
.fa-eye-slash::before { content: "\f10a"; }
.fa-facebook-square::before { content: "\f10b"; }
.fa-filter::before { content: "\f10c"; }
.fa-flag::before { content: "\f10d"; }
.fa-floppy-o::before, .fa-save::before { content: "\f10e"; }
.fa-gavel::before, .fa-legal::before { content: "\f10f"; }
.fa-github::before { content: "\f110"; }
.fa-globe::before { content: "\f111"; }
.fa-google::before { content: "\f112"; }
.fa-history::before { content: "\f113"; }
.fa-key-modern::before { content: "\f114"; }
.fa-link::before { content: "\f115"; }
.fa-pencil-square-o::before, .fa-edit::before { content: "\f116"; }
.fa-question-circle::before { content: "\f117"; }
.fa-quote-left::before { content: "\f118"; }
.fa-reply::before { content: "\f119"; }
.fa-rss::before { content: "\f11a"; }
.fa-search::before { content: "\f11b"; }
.fa-share-alt::before { content: "\f11c"; }
.fa-sign-in::before { content: "\f11d"; }
.fa-sign-out::before { content: "\f11e"; }
.fa-sliders::before { content: "\f11f"; }
.fa-sort::before { content: "\f120"; }
.fa-sort-asc::before { content: "\f121"; }
.fa-sort-desc::before { content: "\f122"; }
.fa-star::before { content: "\f123"; }
.fa-star-o::before { content: "\f124"; }
.fa-table::before { content: "\f125"; }
.fa-times::before, .fa-close::before { content: "\f126"; }
.fa-trash::before { content: "\f127"; }
.fa-trash-o::before { content: "\f128"; }
.fa-user-circle-o::before { content: "\f129"; }
.fa-user-plus::before { content: "\f12a"; }
.fa-wrench::before { content: "\f12b"; }
.fa-address-card-o::before, .fa-vcard-o::before { content: "\f100"; }
.fa-at::before { content: "\f101"; }
.fa-bell::before { content: "\f102"; }
.fa-bell-o::before { content: "\f103"; }
.fa-calendar::before { content: "\f104"; }
.fa-check::before { content: "\f105"; }
.fa-clock-o::before { content: "\f106"; }
.fa-cloud-upload::before { content: "\f107"; }
.fa-code-fork::before { content: "\f108"; }
.fa-download::before { content: "\f109"; }
.fa-eye::before { content: "\f10a"; }
.fa-eye-slash::before { content: "\f10b"; }
.fa-facebook-square::before { content: "\f10c"; }
.fa-filter::before { content: "\f10d"; }
.fa-flag::before { content: "\f10e"; }
.fa-floppy-o::before, .fa-save::before { content: "\f10f"; }
.fa-gavel::before, .fa-legal::before { content: "\f110"; }
.fa-github::before { content: "\f111"; }
.fa-globe::before { content: "\f112"; }
.fa-google::before { content: "\f113"; }
.fa-history::before { content: "\f114"; }
.fa-key-modern::before { content: "\f115"; }
.fa-link::before { content: "\f116"; }
.fa-pencil-square-o::before, .fa-edit::before { content: "\f117"; }
.fa-question-circle::before { content: "\f118"; }
.fa-quote-left::before { content: "\f119"; }
.fa-reply::before { content: "\f11a"; }
.fa-rss::before { content: "\f11b"; }
.fa-search::before { content: "\f11c"; }
.fa-share-alt::before { content: "\f11d"; }
.fa-sign-in::before { content: "\f11e"; }
.fa-sign-out::before { content: "\f11f"; }
.fa-sliders::before { content: "\f120"; }
.fa-sort::before { content: "\f121"; }
.fa-sort-asc::before { content: "\f122"; }
.fa-sort-desc::before { content: "\f123"; }
.fa-star::before { content: "\f124"; }
.fa-star-o::before { content: "\f125"; }
.fa-table::before { content: "\f126"; }
.fa-times::before, .fa-close::before { content: "\f127"; }
.fa-trash::before { content: "\f128"; }
.fa-trash-o::before { content: "\f129"; }
.fa-user-circle-o::before { content: "\f12a"; }
.fa-user-plus::before { content: "\f12b"; }
.fa-wrench::before { content: "\f12c"; }

Binary file not shown.

@ -1,11 +1,11 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<!--
2018-7-22: Created with FontForge (http://fontforge.org)
2018-7-25: Created with FontForge (http://fontforge.org)
-->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<metadata>
Created by FontForge 20170805 at Sun Jul 22 23:07:59 2018
Created by FontForge 20170805 at Wed Jul 25 20:38:52 2018
By ondra
The Fork Awesome font is licensed under the SIL OFL 1.1 (http://scripts.sil.org/OFL). Fork Awesome is a fork based of off Font Awesome 4.7.0 by Dave Gandy. More info on licenses at https://forkawesome.github.io
</metadata>
@ -22,165 +22,170 @@ The Fork Awesome font is licensed under the SIL OFL 1.1 (http://scripts.sil.org/
bbox="-0.0376684 -256 2048 1536.01"
underline-thickness="89.6"
underline-position="-179.2"
unicode-range="U+0020-F12B"
unicode-range="U+0020-F12C"
/>
<missing-glyph />
<glyph glyph-name="space" unicode=" " horiz-adv-x="200"
/>
<glyph glyph-name="at" unicode="&#xf100;"
<glyph glyph-name="address-card-o" unicode="&#xf100;" horiz-adv-x="2048"
d="M1024 405c0 -87 -57 -149 -128 -149h-512c-71 0 -128 62 -128 149c0 155 38 327 196 327c49 -28 115 -76 188 -76s139 48 188 76c158 0 196 -172 196 -327zM867 925c0 -126 -102 -227 -227 -227s-227 101 -227 227c0 125 102 227 227 227s227 -102 227 -227zM1792 480
v-64c0 -18 -14 -32 -32 -32h-576c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h576c18 0 32 -14 32 -32zM1792 732v-56c0 -20 -16 -36 -36 -36h-568c-20 0 -36 16 -36 36v56c0 20 16 36 36 36h568c20 0 36 -16 36 -36zM1792 992v-64c0 -18 -14 -32 -32 -32h-576
c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h576c18 0 32 -14 32 -32zM1920 32v1216c0 17 -15 32 -32 32h-1728c-17 0 -32 -15 -32 -32v-1216c0 -17 15 -32 32 -32h352v96c0 18 14 32 32 32h64c18 0 32 -14 32 -32v-96h768v96c0 18 14 32 32 32h64c18 0 32 -14 32 -32v-96h352
c17 0 32 15 32 32zM2048 1248v-1216c0 -88 -72 -160 -160 -160h-1728c-88 0 -160 72 -160 160v1216c0 88 72 160 160 160h1728c88 0 160 -72 160 -160z" />
<glyph glyph-name="at" unicode="&#xf101;"
d="M972 761c0 144 -75 230 -201 230c-166 0 -344 -165 -344 -432c0 -149 74 -234 204 -234c201 0 341 230 341 436zM1536 640c0 -311 -222 -428 -412 -434c-13 0 -18 -1 -32 -1c-62 0 -111 18 -142 53c-19 22 -30 50 -33 83c-62 -78 -170 -154 -305 -154
c-215 0 -338 133 -338 365c0 319 221 578 491 578c117 0 211 -50 261 -135l2 19l11 56c1 8 8 18 15 18h118c5 0 10 -7 13 -11c3 -3 4 -11 3 -16l-120 -614c-4 -19 -5 -34 -5 -48c0 -54 16 -65 57 -65c68 2 288 30 288 306c0 389 -251 640 -640 640
c-353 0 -640 -287 -640 -640s287 -640 640 -640c147 0 291 51 405 144c14 12 34 10 45 -4l41 -49c5 -7 8 -15 7 -24c-1 -8 -5 -16 -12 -22c-136 -111 -309 -173 -486 -173c-423 0 -768 345 -768 768s345 768 768 768c459 0 768 -309 768 -768z" />
<glyph glyph-name="bell" unicode="&#xf101;" horiz-adv-x="1664"
<glyph glyph-name="bell" unicode="&#xf102;" horiz-adv-x="1664"
d="M848 -160c0 9 -7 16 -16 16c-79 0 -144 65 -144 144c0 9 -7 16 -16 16s-16 -7 -16 -16c0 -97 79 -176 176 -176c9 0 16 7 16 16zM182 128h1300c-179 202 -266 476 -266 832c0 129 -122 320 -384 320s-384 -191 -384 -320c0 -356 -87 -630 -266 -832zM1664 128
c0 -70 -58 -128 -128 -128h-448c0 -141 -115 -256 -256 -256s-256 115 -256 256h-448c-70 0 -128 58 -128 128c148 125 320 349 320 832c0 192 159 402 424 441c-5 12 -8 25 -8 39c0 53 43 96 96 96s96 -43 96 -96c0 -14 -3 -27 -8 -39c265 -39 424 -249 424 -441
c0 -483 172 -707 320 -832z" />
<glyph glyph-name="bell-o" unicode="&#xf102;" horiz-adv-x="1664"
<glyph glyph-name="bell-o" unicode="&#xf103;" horiz-adv-x="1664"
d="M848 -160c0 9 -7 16 -16 16c-79 0 -144 65 -144 144c0 9 -7 16 -16 16s-16 -7 -16 -16c0 -97 79 -176 176 -176c9 0 16 7 16 16zM1664 128c0 -70 -58 -128 -128 -128h-448c0 -141 -115 -256 -256 -256s-256 115 -256 256h-448c-70 0 -128 58 -128 128
c148 125 320 349 320 832c0 192 159 402 424 441c-5 12 -8 25 -8 39c0 53 43 96 96 96s96 -43 96 -96c0 -14 -3 -27 -8 -39c265 -39 424 -249 424 -441c0 -483 172 -707 320 -832z" />
<glyph glyph-name="calendar" unicode="&#xf103;" horiz-adv-x="1664"
<glyph glyph-name="calendar" unicode="&#xf104;" horiz-adv-x="1664"
d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z
M512 1088v288c0 17 -15 32 -32 32h-64c-17 0 -32 -15 -32 -32v-288c0 -17 15 -32 32 -32h64c17 0 32 15 32 32zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288c0 17 -15 32 -32 32h-64c-17 0 -32 -15 -32 -32v-288
c0 -17 15 -32 32 -32h64c17 0 32 15 32 32zM1664 1152v-1280c0 -70 -58 -128 -128 -128h-1408c-70 0 -128 58 -128 128v1280c0 70 58 128 128 128h128v96c0 88 72 160 160 160h64c88 0 160 -72 160 -160v-96h384v96c0 88 72 160 160 160h64c88 0 160 -72 160 -160v-96h128
c70 0 128 -58 128 -128z" />
<glyph glyph-name="check" unicode="&#xf104;" horiz-adv-x="1550"
<glyph glyph-name="check" unicode="&#xf105;" horiz-adv-x="1550"
d="M1550 970c0 -25 -10 -50 -28 -68l-724 -724l-136 -136c-18 -18 -43 -28 -68 -28s-50 10 -68 28l-136 136l-362 362c-18 18 -28 43 -28 68s10 50 28 68l136 136c18 18 43 28 68 28s50 -10 68 -28l294 -295l656 657c18 18 43 28 68 28s50 -10 68 -28l136 -136
c18 -18 28 -43 28 -68z" />
<glyph glyph-name="clock-o" unicode="&#xf105;"
<glyph glyph-name="clock-o" unicode="&#xf106;"
d="M896 992v-448c0 -18 -14 -32 -32 -32h-320c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h224v352c0 18 14 32 32 32h64c18 0 32 -14 32 -32zM1312 640c0 300 -244 544 -544 544s-544 -244 -544 -544s244 -544 544 -544s544 244 544 544zM1536 640
c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768s768 -344 768 -768z" />
<glyph glyph-name="cloud-upload" unicode="&#xf106;" horiz-adv-x="1920"
<glyph glyph-name="cloud-upload" unicode="&#xf107;" horiz-adv-x="1920"
d="M1280 672c0 8 -3 17 -9 23l-352 352c-6 6 -14 9 -23 9c-8 0 -17 -3 -23 -9l-351 -351c-6 -7 -10 -15 -10 -24c0 -18 14 -32 32 -32h224v-352c0 -17 15 -32 32 -32h192c17 0 32 15 32 32v352h224c18 0 32 15 32 32zM1920 384c0 -212 -172 -384 -384 -384h-1088
c-247 0 -448 201 -448 448c0 174 101 332 258 405c-1 15 -2 29 -2 43c0 283 229 512 512 512c208 0 395 -126 474 -318c46 40 105 62 166 62c141 0 256 -115 256 -256c0 -49 -14 -97 -41 -138c174 -41 297 -196 297 -374z" />
<glyph glyph-name="code-fork" unicode="&#xf107;" horiz-adv-x="1024"
<glyph glyph-name="code-fork" unicode="&#xf108;" horiz-adv-x="1024"
d="M288 64c0 53 -43 96 -96 96s-96 -43 -96 -96s43 -96 96 -96s96 43 96 96zM288 1216c0 53 -43 96 -96 96s-96 -43 -96 -96s43 -96 96 -96s96 43 96 96zM928 1088c0 53 -43 96 -96 96s-96 -43 -96 -96s43 -96 96 -96s96 43 96 96zM1024 1088c0 -71 -39 -133 -96 -166
c-3 -361 -259 -441 -429 -495c-159 -50 -211 -74 -211 -171v-26c57 -33 96 -95 96 -166c0 -106 -86 -192 -192 -192s-192 86 -192 192c0 71 39 133 96 166v820c-57 33 -96 95 -96 166c0 106 86 192 192 192s192 -86 192 -192c0 -71 -39 -133 -96 -166v-497
c51 25 105 42 154 57c186 59 292 103 294 312c-57 33 -96 95 -96 166c0 106 86 192 192 192s192 -86 192 -192z" />
<glyph glyph-name="download" unicode="&#xf108;" horiz-adv-x="1664"
<glyph glyph-name="download" unicode="&#xf109;" horiz-adv-x="1664"
d="M1280 192c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1536 192c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1664 416v-320c0 -53 -43 -96 -96 -96h-1472c-53 0 -96 43 -96 96v320c0 53 43 96 96 96h465l135 -136
c37 -36 85 -56 136 -56s99 20 136 56l136 136h464c53 0 96 -43 96 -96zM1339 985c10 -24 5 -52 -14 -70l-448 -448c-12 -13 -29 -19 -45 -19s-33 6 -45 19l-448 448c-19 18 -24 46 -14 70c10 23 33 39 59 39h256v448c0 35 29 64 64 64h256c35 0 64 -29 64 -64v-448h256
c26 0 49 -16 59 -39z" />
<glyph glyph-name="eye" unicode="&#xf109;" horiz-adv-x="1792"
<glyph glyph-name="eye" unicode="&#xf10a;" horiz-adv-x="1792"
d="M1664 576c-95 147 -225 273 -381 353c40 -68 61 -146 61 -225c0 -247 -201 -448 -448 -448s-448 201 -448 448c0 79 21 157 61 225c-156 -80 -286 -206 -381 -353c171 -264 447 -448 768 -448s597 184 768 448zM944 960c0 26 -22 48 -48 48c-167 0 -304 -137 -304 -304
c0 -26 22 -48 48 -48s48 22 48 48c0 114 94 208 208 208c26 0 48 22 48 48zM1792 576c0 -25 -8 -48 -20 -69c-184 -303 -521 -507 -876 -507s-692 205 -876 507c-12 21 -20 44 -20 69s8 48 20 69c184 302 521 507 876 507s692 -205 876 -507c12 -21 20 -44 20 -69z" />
<glyph glyph-name="eye-slash" unicode="&#xf10a;" horiz-adv-x="1792"
<glyph glyph-name="eye-slash" unicode="&#xf10b;" horiz-adv-x="1792"
d="M555 201l78 141c-116 84 -185 219 -185 362c0 79 21 157 61 225c-156 -80 -286 -206 -381 -353c104 -161 251 -296 427 -375zM944 960c0 26 -22 48 -48 48c-167 0 -304 -137 -304 -304c0 -26 22 -48 48 -48s48 22 48 48c0 115 94 208 208 208c26 0 48 22 48 48z
M1307 1151c0 -2 0 -7 -1 -9c-211 -377 -420 -756 -631 -1133l-49 -89c-6 -10 -17 -16 -28 -16c-18 0 -113 58 -134 70c-10 6 -16 16 -16 28c0 16 34 70 44 87c-194 88 -357 238 -472 418c-13 20 -20 44 -20 69c0 24 7 49 20 69c198 304 507 507 876 507c60 0 121 -6 180 -17
l54 97c6 10 16 16 28 16c18 0 112 -58 133 -70c10 -6 16 -16 16 -27zM1344 704c0 -186 -115 -352 -288 -418l280 502c5 -28 8 -56 8 -84zM1792 576c0 -26 -7 -47 -20 -69c-31 -51 -70 -100 -109 -145c-196 -225 -466 -362 -767 -362l74 132c291 25 538 202 694 444
c-74 115 -169 216 -282 294l63 112c124 -83 249 -208 327 -337c13 -22 20 -43 20 -69z" />
<glyph glyph-name="facebook-square" unicode="&#xf10b;"
<glyph glyph-name="facebook-square" unicode="&#xf10c;"
d="M1248 1408c159 0 288 -129 288 -288v-960c0 -159 -129 -288 -288 -288h-188v595h199l30 232h-229v148c0 67 18 112 115 112l122 1v207c-21 3 -94 9 -178 9c-177 0 -299 -108 -299 -306v-171h-200v-232h200v-595h-532c-159 0 -288 129 -288 288v960c0 159 129 288 288 288
h960z" />
<glyph glyph-name="filter" unicode="&#xf10c;" horiz-adv-x="1408"
<glyph glyph-name="filter" unicode="&#xf10d;" horiz-adv-x="1408"
d="M1403 1241c10 -24 5 -52 -14 -70l-493 -493v-742c0 -26 -16 -49 -39 -59c-8 -3 -17 -5 -25 -5c-17 0 -33 6 -45 19l-256 256c-12 12 -19 28 -19 45v486l-493 493c-19 18 -24 46 -14 70c10 23 33 39 59 39h1280c26 0 49 -16 59 -39z" />
<glyph glyph-name="flag" unicode="&#xf10d;" horiz-adv-x="1728"
<glyph glyph-name="flag" unicode="&#xf10e;" horiz-adv-x="1728"
d="M256 1280c0 -46 -25 -87 -64 -110v-1266c0 -17 -15 -32 -32 -32h-64c-17 0 -32 15 -32 32v1266c-39 23 -64 64 -64 110c0 71 57 128 128 128s128 -57 128 -128zM1728 1216v-763c0 -37 -23 -51 -52 -66c-113 -61 -238 -116 -369 -116c-184 0 -272 140 -490 140
c-159 0 -326 -72 -464 -146c-11 -6 -21 -9 -33 -9c-35 0 -64 29 -64 64v742c0 24 12 41 31 55c24 16 53 30 79 43c126 64 279 120 421 120c157 0 280 -52 419 -117c28 -14 57 -19 88 -19c157 0 326 136 370 136c35 0 64 -29 64 -64z" />
<glyph glyph-name="floppy-o" unicode="&#xf10e;"
<glyph glyph-name="floppy-o" unicode="&#xf10f;"
d="M384 0h768v384h-768v-384zM1280 0h128v896c0 19 -17 60 -30 73l-281 281c-14 14 -53 30 -73 30v-416c0 -53 -43 -96 -96 -96h-576c-53 0 -96 43 -96 96v416h-128v-1280h128v416c0 53 43 96 96 96h832c53 0 96 -43 96 -96v-416zM896 928v320c0 17 -15 32 -32 32h-192
c-17 0 -32 -15 -32 -32v-320c0 -17 15 -32 32 -32h192c17 0 32 15 32 32zM1536 896v-928c0 -53 -43 -96 -96 -96h-1344c-53 0 -96 43 -96 96v1344c0 53 43 96 96 96h928c53 0 126 -30 164 -68l280 -280c38 -38 68 -111 68 -164z" />
<glyph glyph-name="gavel" unicode="&#xf10f;" horiz-adv-x="1731"
<glyph glyph-name="gavel" unicode="&#xf110;" horiz-adv-x="1731"
d="M1731 0c0 -34 -14 -67 -37 -90l-107 -108c-24 -23 -57 -37 -91 -37s-67 14 -90 37l-363 364c-24 23 -38 56 -38 90c0 38 16 69 43 96l-256 256l-126 -126c-9 -9 -21 -14 -34 -14s-25 5 -34 14c30 -30 58 -52 58 -98c0 -26 -10 -49 -28 -68c-34 -36 -70 -84 -124 -84
c-25 0 -50 10 -68 28l-408 408c-18 18 -28 43 -28 68c0 54 48 90 84 124c19 18 42 28 68 28c46 0 68 -28 98 -58c-9 9 -14 21 -14 34s5 25 14 34l348 348c9 9 21 14 34 14s25 -5 34 -14c-30 30 -58 52 -58 98c0 26 10 49 28 68c34 36 70 84 124 84c25 0 50 -10 68 -28
l408 -408c18 -18 28 -43 28 -68c0 -54 -48 -90 -84 -124c-19 -18 -42 -28 -68 -28c-46 0 -68 28 -98 58c9 -9 14 -21 14 -34s-5 -25 -14 -34l-126 -126l256 -256c27 27 58 43 96 43c34 0 67 -14 91 -37l363 -363c23 -24 37 -57 37 -91z" />
<glyph glyph-name="github" unicode="&#xf110;"
<glyph glyph-name="github" unicode="&#xf111;"
d="M768 1408c424 0 768 -344 768 -768c0 -339 -220 -627 -525 -729c-39 -7 -53 17 -53 37c0 25 1 108 1 211c0 72 -24 118 -52 142c171 19 351 84 351 379c0 84 -30 152 -79 206c8 20 34 98 -8 204c-64 20 -211 -79 -211 -79c-61 17 -127 26 -192 26s-131 -9 -192 -26
c0 0 -147 99 -211 79c-42 -106 -16 -184 -8 -204c-49 -54 -79 -122 -79 -206c0 -294 179 -360 350 -379c-22 -20 -42 -54 -49 -103c-44 -20 -156 -54 -223 64c-42 73 -118 79 -118 79c-75 1 -5 -47 -5 -47c50 -23 85 -112 85 -112c45 -137 259 -91 259 -91
c0 -64 1 -124 1 -143c0 -20 -14 -44 -53 -37c-305 102 -525 390 -525 729c0 424 344 768 768 768zM291 305c-2 -4 -8 -5 -13 -2c-6 3 -9 8 -7 12c2 3 7 4 13 2c6 -3 9 -8 7 -12zM322 271c-4 -4 -11 -2 -16 3c-5 6 -6 13 -2 16c4 4 11 2 16 -3c5 -6 6 -13 2 -16zM352 226
c-4 -3 -12 0 -17 7s-5 15 0 18c5 4 13 1 17 -6c5 -7 5 -15 0 -19zM394 184c-4 -5 -13 -4 -20 3c-7 6 -9 15 -4 19c4 5 13 4 20 -3c6 -6 8 -15 4 -19zM451 159c-2 -6 -11 -9 -19 -6c-9 2 -15 9 -13 15s11 9 19 7c9 -3 15 -10 13 -16zM514 154c0 -6 -7 -11 -16 -11
c-10 -1 -17 4 -17 11c0 6 7 11 16 11c9 1 17 -4 17 -11zM572 164c1 -6 -5 -12 -14 -14s-17 2 -18 8c-1 7 5 13 14 15c9 1 17 -3 18 -9z" />
<glyph glyph-name="globe" unicode="&#xf111;"
<glyph glyph-name="globe" unicode="&#xf112;"
d="M768 1404c424 0 768 -344 768 -768s-344 -768 -768 -768s-768 344 -768 768s344 768 768 768zM737 1186v0c-18 0 -40 -7 -58 -7c-27 0 -61 12 -81 0s-18 -37 -27 -55s-28 -34 -28 -54s19 -36 28 -54s2 -47 27 -54s54 36 81 54s69 32 81 54s0 36 0 54s16 39 0 55
c-5 5 -14 7 -23 7zM491 1178h-6s-44 -8 -76 -13c-136 -92 -261 -300 -278 -464c23 -12 46 -22 60 -36c27 -27 83 -27 88 -56s-24 -62 -33 -80s-31 -31 -27 -54s36 -36 54 -54s37 -22 54 -54s20 -98 27 -135c9 -47 23 -85 44 -118c27 -19 72 -44 102 -58c10 28 10 93 16 122
c7 37 13 109 27 135s19 19 28 28s18 15 28 28s17 34 26 52s30 31 26 53s-36 37 -54 55s-29 39 -55 54s-73 18 -101 25s-127 12 -129 13c-2 0 -1 -6 -7 2s-2 39 -2 57s11 34 24 66c13 18 5 10 25 24c10 9 43 -44 57 -44s-3 91 6 100c36 36 128 98 128 136s-37 36 -55 54
s-46 -30 -111 -30s76 103 85 112s23 17 27 27s0 18 0 27s12 22 8 25c-2 1 -4 1 -6 1zM1212 1096c-62 -8 -139 -10 -182 -26c-45 -17 -54 -36 -81 -54s-67 -28 -81 -54s0 -54 0 -81s-26 -68 0 -82s55 37 82 55s63 64 81 54s6 -7 0 -27s-51 -41 -52 -81s102 -73 68 -126
s-188 46 -232 17s-19 -54 -28 -81s-37 -52 -27 -81s52 -34 81 -54s81 -56 82 -58s20 -99 27 -135c14 -73 -27 -199 76 -231c31 14 78 41 106 60c13 34 24 72 35 94c22 44 71 123 80 161s0 37 0 55s7 30 0 54s-36 54 -54 81s-34 64 -54 81s-46 18 -54 27s-4 8 -4 13
s-4 7 5 14s34 8 54 0s36 -36 54 -54s25 -51 54 -54s54 36 81 54c25 17 52 56 76 55c-12 131 -98 312 -193 404z" />
<glyph glyph-name="google" unicode="&#xf112;" horiz-adv-x="1505"
<glyph glyph-name="google" unicode="&#xf113;" horiz-adv-x="1505"
d="M768 750h725c7 -39 12 -77 12 -128c0 -438 -294 -750 -737 -750c-425 0 -768 343 -768 768s343 768 768 768c207 0 381 -76 515 -201l-209 -201c-57 55 -157 119 -306 119c-262 0 -476 -217 -476 -485s214 -485 476 -485c304 0 418 218 436 331h-436v264z" />
<glyph glyph-name="history" unicode="&#xf113;"
<glyph glyph-name="history" unicode="&#xf114;"
d="M1536 640c0 -423 -345 -768 -768 -768c-229 0 -445 101 -591 277c-10 13 -9 32 2 43l137 138c7 6 16 9 25 9c9 -1 18 -5 23 -12c98 -127 245 -199 404 -199c282 0 512 230 512 512s-230 512 -512 512c-131 0 -255 -50 -348 -137l137 -138c19 -18 24 -46 14 -69
c-10 -24 -33 -40 -59 -40h-448c-35 0 -64 29 -64 64v448c0 26 16 49 40 59c23 10 51 5 69 -14l130 -129c141 133 332 212 529 212c423 0 768 -345 768 -768zM896 928v-448c0 -18 -14 -32 -32 -32h-320c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h224v352c0 18 14 32 32 32h64
c18 0 32 -14 32 -32z" />
<glyph glyph-name="key-modern" unicode="&#xf114;" horiz-adv-x="1792"
<glyph glyph-name="key-modern" unicode="&#xf115;" horiz-adv-x="1792"
d="M546 1536v0c139 1 278 -52 383 -158c142 -141 187 -343 137 -525l726 -726v-319c0 -35 -29 -64 -64 -64h-300l-45 45l135 226l-46 45l-225 -135l-45 46l134 225l-45 45l-225 -134l-46 45l135 225l-45 46l-243 -139l-186 186c-182 -50 -382 -5 -524 136
c-211 212 -209 556 4 770c107 106 246 159 385 160zM405 1290v0c-41 0 -82 -16 -113 -47c-63 -63 -63 -163 0 -226s164 -63 227 0s63 163 0 226c-31 31 -73 47 -114 47z" />
<glyph glyph-name="link" unicode="&#xf115;" horiz-adv-x="1632"
<glyph glyph-name="link" unicode="&#xf116;" horiz-adv-x="1632"
d="M1440 320c0 26 -10 50 -28 68l-208 208c-18 18 -43 28 -68 28c-29 0 -52 -11 -72 -32c33 -33 72 -61 72 -112c0 -53 -43 -96 -96 -96c-51 0 -79 39 -112 72c-21 -20 -33 -43 -33 -73c0 -25 10 -50 28 -68l206 -207c18 -18 43 -27 68 -27s50 9 68 26l147 146
c18 18 28 42 28 67zM737 1025c0 25 -10 50 -28 68l-206 207c-18 18 -43 28 -68 28s-50 -10 -68 -27l-147 -146c-18 -18 -28 -42 -28 -67c0 -26 10 -50 28 -68l208 -208c18 -18 43 -27 68 -27c29 0 52 10 72 31c-33 33 -72 61 -72 112c0 53 43 96 96 96c51 0 79 -39 112 -72
c21 20 33 43 33 73zM1632 320c0 -76 -31 -150 -85 -203l-147 -146c-54 -54 -127 -83 -203 -83c-77 0 -150 30 -204 85l-206 207c-54 54 -83 127 -83 203c0 79 32 154 88 209l-88 88c-55 -56 -129 -88 -208 -88c-76 0 -150 30 -204 84l-208 208c-55 55 -84 127 -84 204
c0 76 31 150 85 203l147 146c54 54 127 83 203 83c77 0 150 -30 204 -85l206 -207c54 -54 83 -127 83 -203c0 -79 -32 -154 -88 -209l88 -88c55 56 129 88 208 88c76 0 150 -30 204 -84l208 -208c55 -55 84 -127 84 -204z" />
<glyph glyph-name="pencil-square-o" unicode="&#xf116;" horiz-adv-x="1784"
<glyph glyph-name="pencil-square-o" unicode="&#xf117;" horiz-adv-x="1784"
d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072c-9 9 -24 8 -33 -1l-350 -350c-9 -9 -10 -24 -1 -33s24 -8 33 1l350 350c9 9 10 24 1 33zM1408 478v-190c0 -159 -129 -288 -288 -288h-832c-159 0 -288 129 -288 288v832c0 159 129 288 288 288h832
c40 0 80 -8 117 -25c9 -4 16 -13 18 -23c2 -11 -1 -21 -9 -29l-49 -49c-9 -9 -21 -12 -32 -8c-15 4 -30 6 -45 6h-832c-88 0 -160 -72 -160 -160v-832c0 -88 72 -160 160 -160h832c88 0 160 72 160 160v126c0 8 3 16 9 22l64 64c10 10 23 12 35 7s20 -16 20 -29zM1312 1216
l288 -288l-672 -672h-288v288zM1756 1084l-92 -92l-288 288l92 92c37 37 99 37 136 0l152 -152c37 -37 37 -99 0 -136z" />
<glyph glyph-name="question-circle" unicode="&#xf117;"
<glyph glyph-name="question-circle" unicode="&#xf118;"
d="M896 160v192c0 18 -14 32 -32 32h-192c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h192c18 0 32 14 32 32zM1152 832c0 183 -192 320 -364 320c-163 0 -285 -70 -371 -213c-9 -14 -5 -32 8 -42l132 -100c5 -4 12 -6 19 -6c9 0 19 4 25 12c47 60 67 78 86 92
c17 12 50 24 86 24c64 0 123 -41 123 -85c0 -52 -27 -78 -88 -106c-71 -32 -168 -115 -168 -212v-36c0 -18 14 -32 32 -32h192c18 0 32 14 32 32c0 23 29 72 76 99c76 43 180 101 180 253zM1536 640c0 -424 -344 -768 -768 -768s-768 344 -768 768s344 768 768 768
s768 -344 768 -768z" />
<glyph glyph-name="quote-left" unicode="&#xf118;" horiz-adv-x="1664"
<glyph glyph-name="quote-left" unicode="&#xf119;" horiz-adv-x="1664"
d="M768 576v-384c0 -106 -86 -192 -192 -192h-384c-106 0 -192 86 -192 192v704c0 282 230 512 512 512h64c35 0 64 -29 64 -64v-128c0 -35 -29 -64 -64 -64h-64c-141 0 -256 -115 -256 -256v-32c0 -53 43 -96 96 -96h224c106 0 192 -86 192 -192zM1664 576v-384
c0 -106 -86 -192 -192 -192h-384c-106 0 -192 86 -192 192v704c0 282 230 512 512 512h64c35 0 64 -29 64 -64v-128c0 -35 -29 -64 -64 -64h-64c-141 0 -256 -115 -256 -256v-32c0 -53 43 -96 96 -96h224c106 0 192 -86 192 -192z" />
<glyph glyph-name="reply" unicode="&#xf119;" horiz-adv-x="1792"
<glyph glyph-name="reply" unicode="&#xf11a;" horiz-adv-x="1792"
d="M1792 416c0 -140 -70 -323 -127 -451c-11 -23 -22 -55 -37 -76c-7 -10 -14 -17 -28 -17c-20 0 -32 16 -32 35c0 16 4 34 5 50c3 41 5 82 5 123c0 477 -283 560 -714 560h-224v-256c0 -35 -29 -64 -64 -64c-17 0 -33 7 -45 19l-512 512c-12 12 -19 28 -19 45s7 33 19 45
l512 512c12 12 28 19 45 19c35 0 64 -29 64 -64v-256h224c328 0 736 -58 875 -403c42 -106 53 -221 53 -333z" />
<glyph glyph-name="rss" unicode="&#xf11a;" horiz-adv-x="1408"
<glyph glyph-name="rss" unicode="&#xf11b;" horiz-adv-x="1408"
d="M384 192c0 -106 -86 -192 -192 -192s-192 86 -192 192s86 192 192 192s192 -86 192 -192zM896 69c1 -18 -5 -35 -17 -48c-12 -14 -29 -21 -47 -21h-135c-33 0 -60 25 -63 58c-29 305 -271 547 -576 576c-33 3 -58 30 -58 63v135c0 18 7 35 21 47c11 11 27 17 43 17h5
c213 -17 414 -110 565 -262c152 -151 245 -352 262 -565zM1408 67c1 -17 -5 -34 -18 -47c-12 -13 -28 -20 -46 -20h-143c-34 0 -62 26 -64 60c-33 581 -496 1044 -1077 1078c-34 2 -60 30 -60 63v143c0 18 7 34 20 46c12 12 28 18 44 18h3c350 -18 679 -165 927 -414
c249 -248 396 -577 414 -927z" />
<glyph glyph-name="search" unicode="&#xf11b;" horiz-adv-x="1664"
<glyph glyph-name="search" unicode="&#xf11c;" horiz-adv-x="1664"
d="M1152 704c0 247 -201 448 -448 448s-448 -201 -448 -448s201 -448 448 -448s448 201 448 448zM1664 -128c0 -70 -58 -128 -128 -128c-34 0 -67 14 -90 38l-343 342c-117 -81 -257 -124 -399 -124c-389 0 -704 315 -704 704s315 704 704 704s704 -315 704 -704
c0 -142 -43 -282 -124 -399l343 -343c23 -23 37 -56 37 -90z" />
<glyph glyph-name="share-alt" unicode="&#xf11c;"
<glyph glyph-name="share-alt" unicode="&#xf11d;"
d="M1216 512c177 0 320 -143 320 -320s-143 -320 -320 -320s-320 143 -320 320c0 11 1 23 2 34l-360 180c-57 -53 -134 -86 -218 -86c-177 0 -320 143 -320 320s143 320 320 320c84 0 161 -33 218 -86l360 180c-1 11 -2 23 -2 34c0 177 143 320 320 320s320 -143 320 -320
s-143 -320 -320 -320c-84 0 -161 33 -218 86l-360 -180c1 -11 2 -23 2 -34s-1 -23 -2 -34l360 -180c57 53 134 86 218 86z" />
<glyph glyph-name="sign-in" unicode="&#xf11d;"
<glyph glyph-name="sign-in" unicode="&#xf11e;"
d="M1184 640c0 -17 -7 -33 -19 -45l-544 -544c-12 -12 -28 -19 -45 -19c-35 0 -64 29 -64 64v288h-448c-35 0 -64 29 -64 64v384c0 35 29 64 64 64h448v288c0 35 29 64 64 64c17 0 33 -7 45 -19l544 -544c12 -12 19 -28 19 -45zM1536 992v-704c0 -159 -129 -288 -288 -288
h-320c-17 0 -32 15 -32 32c0 28 -13 96 32 96h320c88 0 160 72 160 160v704c0 88 -72 160 -160 160h-288c-25 0 -64 -5 -64 32c0 28 -13 96 32 96h320c159 0 288 -129 288 -288z" />
<glyph glyph-name="sign-out" unicode="&#xf11e;" horiz-adv-x="1568"
<glyph glyph-name="sign-out" unicode="&#xf11f;" horiz-adv-x="1568"
d="M640 96c0 -28 13 -96 -32 -96h-320c-159 0 -288 129 -288 288v704c0 159 129 288 288 288h320c17 0 32 -15 32 -32c0 -28 13 -96 -32 -96h-320c-88 0 -160 -72 -160 -160v-704c0 -88 72 -160 160 -160h288c25 0 64 5 64 -32zM1568 640c0 -17 -7 -33 -19 -45l-544 -544
c-12 -12 -28 -19 -45 -19c-35 0 -64 29 -64 64v288h-448c-35 0 -64 29 -64 64v384c0 35 29 64 64 64h448v288c0 35 29 64 64 64c17 0 33 -7 45 -19l544 -544c12 -12 19 -28 19 -45z" />
<glyph glyph-name="sliders" unicode="&#xf11f;"
<glyph glyph-name="sliders" unicode="&#xf120;"
d="M352 128v-128h-352v128h352zM704 256c35 0 64 -29 64 -64v-256c0 -35 -29 -64 -64 -64h-256c-35 0 -64 29 -64 64v256c0 35 29 64 64 64h256zM864 640v-128h-864v128h864zM224 1152v-128h-224v128h224zM1536 128v-128h-736v128h736zM576 1280c35 0 64 -29 64 -64v-256
c0 -35 -29 -64 -64 -64h-256c-35 0 -64 29 -64 64v256c0 35 29 64 64 64h256zM1216 768c35 0 64 -29 64 -64v-256c0 -35 -29 -64 -64 -64h-256c-35 0 -64 29 -64 64v256c0 35 29 64 64 64h256zM1536 640v-128h-224v128h224zM1536 1152v-128h-864v128h864z" />
<glyph glyph-name="sort" unicode="&#xf120;" horiz-adv-x="1024"
<glyph glyph-name="sort" unicode="&#xf121;" horiz-adv-x="1024"
d="M1024 448c0 -17 -7 -33 -19 -45l-448 -448c-12 -12 -28 -19 -45 -19s-33 7 -45 19l-448 448c-12 12 -19 28 -19 45c0 35 29 64 64 64h896c35 0 64 -29 64 -64zM1024 832c0 -35 -29 -64 -64 -64h-896c-35 0 -64 29 -64 64c0 17 7 33 19 45l448 448c12 12 28 19 45 19
s33 -7 45 -19l448 -448c12 -12 19 -28 19 -45z" />
<glyph glyph-name="sort-asc" unicode="&#xf121;" horiz-adv-x="1024"
<glyph glyph-name="sort-asc" unicode="&#xf122;" horiz-adv-x="1024"
d="M1024 832c0 -35 -29 -64 -64 -64h-896c-35 0 -64 29 -64 64c0 17 7 33 19 45l448 448c12 12 28 19 45 19s33 -7 45 -19l448 -448c12 -12 19 -28 19 -45z" />
<glyph glyph-name="sort-desc" unicode="&#xf122;" horiz-adv-x="1024"
<glyph glyph-name="sort-desc" unicode="&#xf123;" horiz-adv-x="1024"
d="M1024 448c0 -17 -7 -33 -19 -45l-448 -448c-12 -12 -28 -19 -45 -19s-33 7 -45 19l-448 448c-12 12 -19 28 -19 45c0 35 29 64 64 64h896c35 0 64 -29 64 -64z" />
<glyph glyph-name="star" unicode="&#xf123;" horiz-adv-x="1664"
<glyph glyph-name="star" unicode="&#xf124;" horiz-adv-x="1664"
d="M1664 889c0 -18 -13 -35 -26 -48l-363 -354l86 -500c1 -7 1 -13 1 -20c0 -26 -12 -50 -41 -50c-14 0 -28 5 -40 12l-449 236l-449 -236c-13 -7 -26 -12 -40 -12c-29 0 -42 24 -42 50c0 7 1 13 2 20l86 500l-364 354c-12 13 -25 30 -25 48c0 30 31 42 56 46l502 73
l225 455c9 19 26 41 49 41s40 -22 49 -41l225 -455l502 -73c24 -4 56 -16 56 -46z" />
<glyph glyph-name="star-o" unicode="&#xf124;" horiz-adv-x="1664"
<glyph glyph-name="star-o" unicode="&#xf125;" horiz-adv-x="1664"
d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889c0 -18 -13 -35 -26 -48l-363 -354l86 -500c1 -7 1 -13 1 -20c0 -27 -12 -50 -41 -50c-14 0 -28 5 -40 12l-449 236l-449 -236c-13 -7 -26 -12 -40 -12
c-29 0 -42 24 -42 50c0 7 1 13 2 20l86 500l-364 354c-12 13 -25 30 -25 48c0 30 31 42 56 46l502 73l225 455c9 19 26 41 49 41s40 -22 49 -41l225 -455l502 -73c24 -4 56 -16 56 -46z" />
<glyph glyph-name="table" unicode="&#xf125;" horiz-adv-x="1664"
<glyph glyph-name="table" unicode="&#xf126;" horiz-adv-x="1664"
d="M512 160v192c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h320c18 0 32 14 32 32zM512 544v192c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h320c18 0 32 14 32 32zM1024 160v192c0 18 -14 32 -32 32h-320
c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h320c18 0 32 14 32 32zM512 928v192c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h320c18 0 32 14 32 32zM1024 544v192c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-192
c0 -18 14 -32 32 -32h320c18 0 32 14 32 32zM1536 160v192c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h320c18 0 32 14 32 32zM1024 928v192c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h320c18 0 32 14 32 32z
M1536 544v192c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h320c18 0 32 14 32 32zM1536 928v192c0 18 -14 32 -32 32h-320c-18 0 -32 -14 -32 -32v-192c0 -18 14 -32 32 -32h320c18 0 32 14 32 32zM1664 1248v-1088c0 -88 -72 -160 -160 -160
h-1344c-88 0 -160 72 -160 160v1088c0 88 72 160 160 160h1344c88 0 160 -72 160 -160z" />
<glyph glyph-name="times" unicode="&#xf126;" horiz-adv-x="1188"
<glyph glyph-name="times" unicode="&#xf127;" horiz-adv-x="1188"
d="M1188 214c0 -25 -10 -50 -28 -68l-136 -136c-18 -18 -43 -28 -68 -28s-50 10 -68 28l-294 294l-294 -294c-18 -18 -43 -28 -68 -28s-50 10 -68 28l-136 136c-18 18 -28 43 -28 68s10 50 28 68l294 294l-294 294c-18 18 -28 43 -28 68s10 50 28 68l136 136
c18 18 43 28 68 28s50 -10 68 -28l294 -294l294 294c18 18 43 28 68 28s50 -10 68 -28l136 -136c18 -18 28 -43 28 -68s-10 -50 -28 -68l-294 -294l294 -294c18 -18 28 -43 28 -68z" />
<glyph glyph-name="trash" unicode="&#xf127;" horiz-adv-x="1408"
<glyph glyph-name="trash" unicode="&#xf128;" horiz-adv-x="1408"
d="M512 160v704c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-704c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM768 160v704c0 18 -14 32 -32 32h-64c-18 0 -32 -14 -32 -32v-704c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM1024 160v704c0 18 -14 32 -32 32h-64
c-18 0 -32 -14 -32 -32v-704c0 -18 14 -32 32 -32h64c18 0 32 14 32 32zM480 1152h448l-48 117c-3 4 -12 10 -17 11h-317c-6 -1 -14 -7 -17 -11zM1408 1120v-64c0 -18 -14 -32 -32 -32h-96v-948c0 -110 -72 -204 -160 -204h-832c-88 0 -160 90 -160 200v952h-96
c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h309l70 167c20 49 80 89 133 89h320c53 0 113 -40 133 -89l70 -167h309c18 0 32 -14 32 -32z" />
<glyph glyph-name="trash-o" unicode="&#xf128;" horiz-adv-x="1408"
<glyph glyph-name="trash-o" unicode="&#xf129;" horiz-adv-x="1408"
d="M512 800v-576c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v576c0 18 14 32 32 32h64c18 0 32 -14 32 -32zM768 800v-576c0 -18 -14 -32 -32 -32h-64c-18 0 -32 14 -32 32v576c0 18 14 32 32 32h64c18 0 32 -14 32 -32zM1024 800v-576c0 -18 -14 -32 -32 -32h-64
c-18 0 -32 14 -32 32v576c0 18 14 32 32 32h64c18 0 32 -14 32 -32zM1152 76v948h-896v-948c0 -48 27 -76 32 -76h832c5 0 32 28 32 76zM480 1152h448l-48 117c-3 4 -12 10 -17 11h-317c-6 -1 -14 -7 -17 -11zM1408 1120v-64c0 -18 -14 -32 -32 -32h-96v-948
c0 -110 -72 -204 -160 -204h-832c-88 0 -160 90 -160 200v952h-96c-18 0 -32 14 -32 32v64c0 18 14 32 32 32h309l70 167c20 49 80 89 133 89h320c53 0 113 -40 133 -89l70 -167h309c18 0 32 -14 32 -32z" />
<glyph glyph-name="user-circle-o" unicode="&#xf129;" horiz-adv-x="1792"
<glyph glyph-name="user-circle-o" unicode="&#xf12a;" horiz-adv-x="1792"
d="M896 1536c495 0 896 -401 896 -896c0 -492 -399 -896 -896 -896c-496 0 -896 403 -896 896c0 495 401 896 896 896zM1515 185c93 128 149 285 149 455c0 423 -345 768 -768 768s-768 -345 -768 -768c0 -170 56 -327 149 -455c36 179 123 327 306 327
c81 -79 191 -128 313 -128s232 49 313 128c183 0 270 -148 306 -327zM1280 832c0 -212 -172 -384 -384 -384s-384 172 -384 384s172 384 384 384s384 -172 384 -384z" />
<glyph glyph-name="user-plus" unicode="&#xf12a;" horiz-adv-x="2048"
<glyph glyph-name="user-plus" unicode="&#xf12b;" horiz-adv-x="2048"
d="M704 640c-212 0 -384 172 -384 384s172 384 384 384s384 -172 384 -384s-172 -384 -384 -384zM1664 512h352c17 0 32 -15 32 -32v-192c0 -17 -15 -32 -32 -32h-352v-352c0 -17 -15 -32 -32 -32h-192c-17 0 -32 15 -32 32v352h-352c-17 0 -32 15 -32 32v192
c0 17 15 32 32 32h352v352c0 17 15 32 32 32h192c17 0 32 -15 32 -32v-352zM928 288c0 -70 58 -128 128 -128h256v-238c-49 -36 -111 -50 -171 -50h-874c-160 0 -267 96 -267 259c0 226 53 573 346 573c16 0 27 -7 39 -17c98 -75 193 -122 319 -122s221 47 319 122
c12 10 23 17 39 17c85 0 160 -32 217 -96h-223c-70 0 -128 -58 -128 -128v-192z" />
<glyph glyph-name="wrench" unicode="&#xf12b;" horiz-adv-x="1641"
<glyph glyph-name="wrench" unicode="&#xf12c;" horiz-adv-x="1641"
d="M363 64c0 35 -29 64 -64 64s-64 -29 -64 -64s29 -64 64 -64s64 29 64 64zM1007 484l-682 -682c-23 -23 -56 -37 -90 -37s-67 14 -91 37l-106 108c-24 23 -38 56 -38 90s14 67 38 91l681 681c52 -131 157 -236 288 -288zM1641 919c0 -33 -12 -74 -23 -106
c-63 -178 -234 -301 -423 -301c-247 0 -448 201 -448 448s201 448 448 448c73 0 168 -22 229 -63c10 -7 16 -16 16 -28c0 -11 -7 -22 -16 -28l-293 -169v-224l193 -107c33 19 265 165 285 165s32 -15 32 -35z" />
</font>

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Binary file not shown.

@ -11,3 +11,7 @@
.fa-large {
font-size: 1.6em;
}
.fa-huge {
font-size: 2em;
}

@ -18,3 +18,11 @@
display: none;
}
}
.border-dashed {
border-style: dashed !important;
}
.border-dotted {
border-style: dotted !important;
}

@ -13,7 +13,7 @@
@php(Widget::setLayout(4, 6))
{!! Widget::email('email', 'E-Mail Address')->required()->autofocus() !!}
{!! Widget::text('login', 'Username or E-Mail')->required()->autofocus() !!}
{!! Widget::password('password', 'Password')->required() !!}
{!! Widget::checkbox('remember', 'Remember Me')->checked(false) !!}

@ -7,7 +7,7 @@
<div class="custom-control custom-checkbox{{ $errors->has($w->name) ? ' is-invalid' : '' }}">
<input type="checkbox" class="custom-control-input"
id="field-{{ $w->name }}"
{{+$w->value?'checked':''}}
{{\MightyPork\Utils\Utils::parseBool($w->value)?'checked':''}}
name="{{ $w->name }}">
<label class="custom-control-label" for="field-{{ $w->name }}">
{{ $w->label }}

@ -35,25 +35,7 @@
</a>
</li>
@else
<li class="nav-item ml-1 d-md-none">
<a class="nav-link" href="{{ route('logout') }}"
onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
{{-- this is some hack against CSRF - logout only via POST --}}
<i class="fa-sign-out fa-pr"></i>{{ __('Logout') }}
</a>
</li>
<li class="nav-item ml-1 d-md-none">
<a class="nav-link" href="{{ route('user.edit') }}">
<i class="fa-sliders fa-pr"></i>{{ __('Settings') }}
</a>
</li>
<li class="nav-item ml-1 d-md-none">
<a class="nav-link" href="{{ route('user.manage-oauth') }}">
<i class="fa-key-modern fa-pr"></i>{{ __('Security') }}
</a>
</li>
@include('layouts.nav-buttons', ['dropdown' => false])
<li class="nav-item dropdown mobile-only">
<a id="mainNavDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown"
@ -63,21 +45,7 @@
</a>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="mainNavDropdown">
<a class="dropdown-item" href="{{ route('logout') }}"
onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
{{-- this is some hack against CSRF - logout only via POST --}}
<i class="fa-sign-out fa-pr"></i>{{ __('Logout') }}
</a>
<a class="dropdown-item" href="{{ route('user.edit') }}">
<i class="fa-sliders fa-pr"></i>{{ __('Settings') }}
</a>
<a class="dropdown-item" href="{{ route('user.manage-oauth') }}">
<i class="fa-key-modern fa-pr"></i>{{ __('Security') }}
</a>
@include('layouts.nav-buttons', ['dropdown' => true])
</div>
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">

@ -0,0 +1,27 @@
@php
$li = $dropdown ? '' : '<li class="nav-item ml-1 d-md-none">';
$endli = $dropdown ? '' : '</li>';
$aclass = $dropdown ? 'dropdown-item' : 'nav-link';
@endphp
{!! $li !!}
<a class="{{ $aclass }}" href="{{ route('profile.edit') }}">
<i class="fa-sliders fa-pr"></i>{{ __('Settings') }}
</a>
{!! $endli !!}
{!! $li !!}
<a class="{{ $aclass }}" href="{{ route('profile.manage-oauth') }}">
<i class="fa-key-modern fa-pr"></i>{{ __('Security') }}
</a>
{!! $endli !!}
{!! $li !!}
<a class="{{ $aclass }}" href="{{ route('logout') }}"
onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
{{-- this is some hack against CSRF - logout only via POST --}}
<i class="fa-sign-out fa-pr"></i>{{ __('Logout') }}
</a>
{!! $endli !!}

@ -0,0 +1,33 @@
{{-- Profile edit form --}}
@extends('layouts.app')
@section('content')
<form method="POST" action="{{route('profile.store')}}" class="row justify-content-center"
aria-label="Your Profile">
@csrf
<div class="col-md-10">
@php(Widget::setLayout(3, 7))
{!! Widget::header(1, 'Settings') !!}
{!! Widget::text('title', 'Display Name')->value($user->title)->required()->autofocus()
->help('Shown on your profile page, tables, comments, etc.') !!}
{!! Widget::textarea('bio', 'About Me')->value($user->bio)->height('8em')
->help('This is shown in your profile box') !!}
{!! Widget::text('website', 'Website')->value($user->website)->prepend('<i class="fa-globe"></i>')
->help('Custom clickable link shown on your profile page.') !!}
<div class="row form-group">
<div class="col-md-7 offset-md-3">
<button type="submit" class="btn btn-primary">
<i class="fa-save pr-2"></i>Save Changes
</button>
</div>
</div>
</div>
</form>
@endsection

@ -0,0 +1,140 @@
{{-- Profile edit form --}}
@extends('layouts.app')
@section('content')
@php(Widget::setLayout(3, 7))
<form method="POST" action="{{route('profile.store')}}" class="row justify-content-center">
@csrf
<div class="col-md-10">
{!! Widget::header(1, 'Login Settings') !!}
{!! Widget::par('Confirm using the save button at the bottom.') !!}
</div>
<div class="col-md-10 mt-3">
{!! Widget::header(2, 'Identifiers') !!}
{!! Widget::par('Caution: Changing username will alter URLs of your tables.') !!}
{!! Widget::text('name', 'Username')->value($user->name)->required()
->prepend('@')
->help('This is part of your vanity URL, and can be also used to login') !!}
{!! Widget::par('E-mail change will apply after you confirm the new address.
We will send you a confirmation link when you submit the form.', 'text-justify') !!}
{!! Widget::email('email', 'E-Mail Address')->value($user->email)->required()
->help('Used to login and for password resets.') !!}
</div>
<div class="col-md-10 mt-3">
{!! Widget::header(2, 'Password Change') !!}
{!! Widget::par('Leave empty to keep your current password (if any).') !!}
{!! Widget::password('new_password', 'New Password') !!}
{!! Widget::password('new_password_confirmation', 'Confirm New Password') !!}
</div>
<div class="col-md-10 mt-3">
<div class="row form-group">
<div class="col-md-7 offset-md-3">
<button type="submit" class="btn btn-primary">
<i class="fa-save pr-2"></i>Apply Changes
</button>
</div>
</div>
</div>
<div class="col-md-10 mt-3">
{!! Widget::header(2, 'OAuth2 Logins') !!}
{!! Widget::par('
Here you can remove identities you do not wish to use anymore.
To completely revoke the authorization, also remove the app
from your provider\'s settings.
', 'text-justify')!!}
<?php
$icons = [
'github' => 'github',
'facebook' => 'facebook-square',
'google' => 'google',
];
?>
@if(!count($user->socialIdentities))
<div class="row form-group">
<div class="col-md-7 offset-md-3 border border-primary border-dashed rounded">
No identities connected.
</div>
</div>
@else
@foreach($user->socialIdentities as $identity)
<div class="row form-group">
<div class="col-md-3 col-form-label text-md-right">
<a href="{{route('forget-identity', ['id' => $identity->getKey()])}}" class="btn btn-danger" role="button">Forget</a>
</div>
<div class="col-md-7 border border-primary rounded p-1 pl-0">
<table>
<tr>
<td rowspan=4>
<i class="fa-{{ $icons[$identity->provider] }} fa-huge py-3 px-4"></i>
</td>
<th>Nickname</th>
<td class="pl-2">{{ $identity->nick_name }}</td>
</tr>
<tr>
<th>Full Name</th>
<td class="pl-2">{{ $identity->full_name }}</td>
</tr>
<tr>
<th>E-Mail</th>
<td class="pl-2">{{ $identity->email }}</td>
</tr>
<tr>
<th>User ID</th>
<td class="pl-2">{{ $identity->provider_user_id }}</td>
</tr>
</table>
</div>
</div>
@endforeach
@endif
{!! Widget::par(
'Click the buttons below to add a new OAuth2 identity.
You will be redirected to the authorization form.',
'text-justify'
)!!}
<div class="row form-group">
<div class="col-md-3 col-form-label text-md-right">
Add identity
</div>
<div class="col-md-7">
@set('services.oauth_providers.github.client_id')
<a type="submit" href="{{route('oauth-github-authorize')}}" class="btn btn-dark">
<i class="fa-github pr-1"></i>
{{ __('GitHub') }}
</a>
@endset
@set('services.oauth_providers.google.client_id')
<a type="submit" href="{{route('oauth-google-authorize')}}" class="btn btn-dark">
<i class="fa-google pr-1"></i>
{{ __('Google') }}
</a>
@endset
@set('services.oauth_providers.facebook.client_id')
<a type="submit" href="{{route('oauth-facebook-authorize')}}" class="btn btn-dark">
<i class="fa-facebook-square pr-1"></i>
{{ __('Facebook') }}
</a>
@endset
</div>
</div>
</div>
</form>
@endsection

@ -16,7 +16,7 @@
<i class="fa-user-circle-o fa-pr fa-large"></i>{{ $user->title }}
@if(authed() && user()->is($user))
<a href="{{route('user.edit')}}" class="btn ml-auto">Edit</a>
<a href="{{route('profile.edit')}}" class="btn ml-auto">Edit</a>
@endif
</div>
@ -84,7 +84,7 @@
@endif
</div>
@include('user._table-list')
@include('profile._table-list')
</div>
</div>

@ -1,49 +0,0 @@
{{-- Profile edit form --}}
@extends('layouts.app')
@section('content')
<form method="POST" action="{{route('user.store')}}" class="row justify-content-center"
aria-label="Your Profile">
@csrf
<div class="col-md-10">
@php(Widget::setLayout(3, 7))
{!! Widget::header(1, 'Settings') !!}
{!! Widget::text('title', 'Display Name')->value($user->title)->required()->autofocus()
->help('Shown on your profile page, tables, comments, etc.') !!}
{!! Widget::text('name', 'Username')->value($user->name)->required()
->prepend('@')
->help('Part of your vanity URL. Caution: changing this will alter URLs of your tables.') !!}
{!! Widget::textarea('bio', 'About Me')->value($user->bio)->height('8em')
->help('This is shown in your profile box') !!}
{!! Widget::text('website', 'Website')->value($user->website)->prepend('<i class="fa-globe"></i>')
->help('Custom clickable link shown on your profile page.') !!}
{!! Widget::email('email', 'E-Mail Address')->value($user->email)->required()
->help('Used to login and for password resets.
This field is protected; a change will be applied only after you confirm
the new e-mail address via a confirmation link we\'ll send you to it.') !!}
{!! Widget::header(3, 'Password Change') !!}
{!! Widget::par('Leave empty to keep your current password (if any).') !!}
{!! Widget::password('new_password', 'New Password') !!}
{!! Widget::password('new_password_confirmation', 'Confirm New Password') !!}
<div class="row form-group">
<div class="col-md-7 offset-md-3">
<button type="submit" class="btn btn-primary">
<i class="fa-save pr-2"></i>Apply Changes
</button>
</div>
</div>
</div>
</form>
@endsection

@ -1,15 +0,0 @@
{{-- Profile edit form --}}
@extends('layouts.app')
@section('content')
<div class="row justify-content-center">
<div class="col-md-10">
@php(Widget::setLayout(3, 7))
{!! Widget::header(1, 'Logins') !!}
<p>TODO social logins, add email & change pw form here</p>
</div>
</div>
@endsection

@ -11,8 +11,24 @@ Auth::routes();
// ----------------- SOCIAL LOGIN --------------------
function _loginVia($method) {
$wasLoggedIn = !guest();
try {
SocialAuth::login($method, function (User $user, ProviderUser $details) {
SocialAuth::login($method, function (User $user, ProviderUser $details) use($wasLoggedIn) {
if ($user->exists && !$wasLoggedIn) {
// check if this identity already existed
if (! $user->socialIdentities()
->where('provider', $details->provider)
->where('provider_user_id', $details->id)
->exists()) {
Auth::logout();
abort(403,
"Account with this e-mail already exists. Add the identity
to the account manually after logging in through an existing
authentication method.");
}
}
// update user name first time user logs in
if (!$user->exists) {
$basename = $details->nickname ?: ($details->full_name ?: $details->email);
@ -28,7 +44,6 @@ function _loginVia($method) {
if ("$user->email" === "") {
$user->email = $details->email;
}
$user->confirmed = true; // mark as confirmed, we trust the provider
});
} catch (ApplicationRejectedException $e) {
@ -36,6 +51,10 @@ function _loginVia($method) {
} catch (InvalidAuthorizationCodeException $e) {
abort(401, $e->getMessage());
}
if ($wasLoggedIn)
return redirect(route('profile.manage-oauth'));
else
return Redirect::intended();
};
@ -66,6 +85,8 @@ Route::get('/auth/facebook/callback', function() {
return _loginVia('facebook');
})->name('oauth-facebook-callback');
Route::get('/auth/forget/{id}', 'ProfileController@forgetSocialLogin')->name('forget-identity');
/*
Route::get('/auth/stack/authorize', function() {
return SocialAuth::authorize('stack');

@ -13,7 +13,7 @@ Route::get('/about/privacy', function () {
Route::get('/', function () {
if (!Auth::guest()) {
return redirect(route('user.view', Auth::user()->name));
return redirect(route('profile.view', Auth::user()->name));
}
return view('welcome');
});
@ -28,15 +28,15 @@ Route::group(['middleware' => 'auth'], function () {
});
Route::group([
'prefix' => 'user',
'prefix' => 'profile',
], function () {
Route::get('edit', 'UserController@edit')->name('user.edit');
Route::post('edit', 'UserController@store')->name('user.store');
Route::get('edit', 'ProfileController@edit')->name('profile.edit');
Route::post('edit', 'ProfileController@store')->name('profile.store');
Route::post('create', 'TableController@storeNew')->name('table.storeNew');
Route::get('logins', 'UserController@manageOauth')->name('user.manage-oauth');
Route::get('logins', 'ProfileController@manageOauth')->name('profile.manage-oauth');
});
});
// Table resource - located at the end to work as a fallback
Route::get('@{user}', 'UserController@view')->name('user.view');
Route::get('@{user}', 'ProfileController@view')->name('profile.view');
Route::get('@{user}/{table}', 'TableController@view')->name('table.view');

@ -93,6 +93,10 @@ class Authenticator
$identity->provider = $providerAlias;
$identity->provider_user_id = $details->id;
$identity->access_token = $details->access_token;
$identity->nick_name = $details->nickname;
$identity->full_name = $details->full_name;
$identity->avatar = $details->avatar;
$identity->email = $details->email;
$this->identities->store($identity);
}
}

@ -8,9 +8,15 @@ use Illuminate\Database\Eloquent\Model;
* @property $provider
* @property $provider_user_id
* @property $access_token
* @property $nick_name
* @property $full_name
* @property $avatar
* @property $email
*/
class OAuthIdentity extends Model
{
protected $guarded = [];
protected static $configuredTable = 'oauth_identities';
public static function configureTable($table)

@ -21,6 +21,11 @@ class FacebookProvider extends OAuth2Provider
'timezone',
];
protected function providerName()
{
return 'facebook';
}
protected function getAuthorizeUrl()
{
return $this->authorizeUrl;

@ -24,6 +24,11 @@ class GitHubProvider extends OAuth2Provider
],
];
protected function providerName()
{
return 'github';
}
protected function getAuthorizeUrl()
{
return $this->authorizeUrl;

@ -21,6 +21,11 @@ class GoogleProvider extends OAuth2Provider
'user_details' => [],
];
protected function providerName()
{
return 'google';
}
protected function compileScopes()
{
return implode(' ', $this->scope);

@ -1,6 +1,7 @@
<?php namespace SocialNorm;
/**
* @property-read string $provider
* @property-read string $access_token
* @property-read string $id
* @property-read string $nickname
@ -12,6 +13,7 @@
*/
class ProviderUser
{
protected $provider;
protected $access_token;
protected $id;
protected $nickname;
@ -28,6 +30,7 @@ class ProviderUser
$this->full_name = $this->fetch($attributes, 'full_name');
$this->avatar = $this->fetch($attributes, 'avatar');
$this->email = $this->fetch($attributes, 'email');
$this->provider = $this->fetch($attributes, 'provider');
$this->raw = $raw;
}

@ -44,6 +44,8 @@ abstract class OAuth2Provider implements Provider
return $this->redirectUri;
}
protected abstract function providerName();
public function authorizeUrl(string $state) : string
{
$url = $this->getAuthorizeUrl();
@ -71,6 +73,7 @@ abstract class OAuth2Provider implements Provider
$this->accessToken = $this->requestAccessToken();
$this->providerUserData = $this->requestUserData();
return new ProviderUser([
'provider' => $this->providerName(),
'access_token' => $this->accessToken,
'id' => $this->userId(),
'nickname' => $this->nickname(),

@ -29,6 +29,11 @@ class StackOverflowProvider extends OAuth2Provider
'user_details' => [],
];
protected function providerName()
{
return 'stack';
}
public function __construct(array $config, HttpClient $httpClient, Request $request)
{
parent::__construct($config, $httpClient, $request);

@ -0,0 +1,11 @@
--- vendor/laravel/framework/src/Illuminate/Auth/EloquentUserProvider.orig.php 2018-07-25 22:46:46.980782012 +0200
+++ vendor/laravel/framework/src/Illuminate/Auth/EloquentUserProvider.php 2018-07-25 22:48:47.490981175 +0200
@@ -121,7 +121,7 @@
if (is_array($value) || $value instanceof Arrayable) {
$query->whereIn($key, $value);
} else {
- $query->where($key, $value);
+ $query->whereRaw('LOWER(' . $key . ')=LOWER(?)', [$value]);
}
}
Loading…
Cancel
Save