Support login workflow

Added basic support for logging in and viewing your home timeline.
Created a sqlite DB for managing app credentials.
This commit is contained in:
St John Karp 2018-08-12 07:26:26 -07:00
parent d7a3e81cff
commit 144848225f
10 changed files with 341 additions and 78 deletions

View File

@ -0,0 +1,73 @@
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Mastodon;
use Illuminate\Support\Facades\DB;
use Socialite;
class LoginController extends Controller
{
public function login()
{
# Check if this app is already registered.
$app = DB::table('apps')->where('server', env('MASTODON_DOMAIN'))->first();
if ($app == null)
{
# Register this app with the API server.
$app_info = Mastodon::domain(env('MASTODON_DOMAIN'))
->createApp(env('APP_NAME'), env('MASTODON_REDIRECT'), config('services.mastodon.scopes'), env('APP_URL'));
$client_id = $app_info['client_id'];
$client_secret = $app_info['client_secret'];
DB::table('apps')->insert([
'server' => env('MASTODON_DOMAIN'),
'client_name' => env('APP_NAME'),
'redirect_uris' => env('MASTODON_REDIRECT'),
'scopes' => join(' ', config('services.mastodon.scopes')),
'website' => env('APP_URL'),
'response_id' => $app_info['id'],
'client_id' => $client_id,
'client_secret' => $client_secret
]);
}
else
{
$client_id = $app->client_id;
$client_secret = $app->client_secret;
}
# Set configs required for the redirect.
config(['services.mastodon.domain' => env('MASTODON_DOMAIN')]);
config(['services.mastodon.client_id' => $client_id]);
config(['services.mastodon.client_secret' => $client_secret]);
# Save this info to the session.
session(['mastodon_domain' => env('MASTODON_DOMAIN')]);
session(['client_id' => $client_id]);
session(['client_secret' => $client_secret]);
# Redirect the user to their instance to log in.
return Socialite::driver('mastodon')->redirect();
}
public function callback()
{
$domain = session('mastodon_domain');
$client_id = session('client_id');
$client_secret = session('client_secret');
config(['services.mastodon.domain' => $domain]);
config(['services.mastodon.client_id' => $client_id]);
config(['services.mastodon.client_secret' => $client_secret]);
# Get user data (token, etc.)
$user = Socialite::driver('mastodon')->user();
session(['user' => $user]);
return redirect()->route('friends');
}
}

View File

@ -7,21 +7,41 @@ use Mastodon;
class TimelineController extends Controller class TimelineController extends Controller
{ {
public function show_timeline() public function public_timeline()
{ {
$public_timeline = Mastodon::domain(env('MASTODON_API')) $timeline = Mastodon::domain(env('MASTODON_DOMAIN'))
->get('/timelines/public', ['local' => true]); ->get('/timelines/public', ['local' => true]);
# Embed images. $timeline = $this->embed_images($timeline);
foreach ($public_timeline as $index => $status)
return view('timeline', ['statuses' => $timeline]);
}
public function home_timeline()
{
$user = session('user');
$timeline = Mastodon::domain(env('MASTODON_DOMAIN'))
->token($user->token)
->get('/timelines/home');
$timeline = $this->embed_images($timeline);
return view('timeline', ['statuses' => $timeline]);
}
private function embed_images($timeline)
{
foreach ($timeline as $index => $status)
{ {
$public_timeline[$index]['content'] = preg_replace( # Search for links to images and replace the inner HTML
# with an img tag of the image itself.
$timeline[$index]['content'] = preg_replace(
'/<a href="([^>]+)\.(png|jpg|jpeg|gif)">([^<]+)<\/a>/', '/<a href="([^>]+)\.(png|jpg|jpeg|gif)">([^<]+)<\/a>/',
'<a href="${1}.${2}"><img src="${1}.${2}" alt="${3}" /></a>', '<a href="${1}.${2}"><img src="${1}.${2}" alt="${3}" /></a>',
$status['content'] $status['content']
); );
} }
return view('timeline', ['statuses' => $public_timeline]); return $timeline;
} }
} }

View File

@ -9,7 +9,8 @@
"fideloper/proxy": "~3.3", "fideloper/proxy": "~3.3",
"laravel/framework": "5.5.*", "laravel/framework": "5.5.*",
"laravel/tinker": "~1.0", "laravel/tinker": "~1.0",
"revolution/laravel-mastodon-api": "^1.5" "revolution/laravel-mastodon-api": "^1.5",
"revolution/socialite-mastodon": "^1.2"
}, },
"require-dev": { "require-dev": {
"filp/whoops": "~2.0", "filp/whoops": "~2.0",

182
composer.lock generated
View File

@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "92f25db138dc11525945a2c977eff7a9", "hash": "777e302fe64df7b4f6c3d53b0d67ca01",
"content-hash": "fe6ad9502bf61c169c783babe3aac2e8", "content-hash": "99e2b15adf8ee6829bad59f44cae2cef",
"packages": [ "packages": [
{ {
"name": "dnoegel/php-xdg-base-dir", "name": "dnoegel/php-xdg-base-dir",
@ -723,6 +723,68 @@
], ],
"time": "2018-08-08 18:22:44" "time": "2018-08-08 18:22:44"
}, },
{
"name": "laravel/socialite",
"version": "v3.0.12",
"source": {
"type": "git",
"url": "https://github.com/laravel/socialite.git",
"reference": "b5f465847b1d637efa86bbfe2fc1c9d2bd12f60f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/socialite/zipball/b5f465847b1d637efa86bbfe2fc1c9d2bd12f60f",
"reference": "b5f465847b1d637efa86bbfe2fc1c9d2bd12f60f",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": "~6.0",
"illuminate/contracts": "~5.4",
"illuminate/http": "~5.4",
"illuminate/support": "~5.4",
"league/oauth1-client": "~1.0",
"php": ">=5.4.0"
},
"require-dev": {
"mockery/mockery": "~0.9",
"phpunit/phpunit": "~4.0|~5.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
},
"laravel": {
"providers": [
"Laravel\\Socialite\\SocialiteServiceProvider"
],
"aliases": {
"Socialite": "Laravel\\Socialite\\Facades\\Socialite"
}
}
},
"autoload": {
"psr-4": {
"Laravel\\Socialite\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "Laravel wrapper around OAuth 1 & OAuth 2 libraries.",
"keywords": [
"laravel",
"oauth"
],
"time": "2018-06-01 15:06:47"
},
{ {
"name": "laravel/tinker", "name": "laravel/tinker",
"version": "v1.0.7", "version": "v1.0.7",
@ -870,6 +932,69 @@
], ],
"time": "2018-05-07 08:44:23" "time": "2018-05-07 08:44:23"
}, },
{
"name": "league/oauth1-client",
"version": "1.7.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/oauth1-client.git",
"reference": "fca5f160650cb74d23fc11aa570dd61f86dcf647"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/fca5f160650cb74d23fc11aa570dd61f86dcf647",
"reference": "fca5f160650cb74d23fc11aa570dd61f86dcf647",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": "^6.0",
"php": ">=5.5.0"
},
"require-dev": {
"mockery/mockery": "^0.9",
"phpunit/phpunit": "^4.0",
"squizlabs/php_codesniffer": "^2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"League\\OAuth1\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ben Corlett",
"email": "bencorlett@me.com",
"homepage": "http://www.webcomm.com.au",
"role": "Developer"
}
],
"description": "OAuth 1.0 Client Library",
"keywords": [
"Authentication",
"SSO",
"authorization",
"bitbucket",
"identity",
"idp",
"oauth",
"oauth1",
"single sign on",
"trello",
"tumblr",
"twitter"
],
"time": "2016-08-17 00:36:58"
},
{ {
"name": "monolog/monolog", "name": "monolog/monolog",
"version": "1.23.0", "version": "1.23.0",
@ -1550,6 +1675,59 @@
], ],
"time": "2018-05-17 06:29:25" "time": "2018-05-17 06:29:25"
}, },
{
"name": "revolution/socialite-mastodon",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/kawax/socialite-mastodon.git",
"reference": "2c5f26cee466fabf5797de46f8a55b5537abfe17"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/kawax/socialite-mastodon/zipball/2c5f26cee466fabf5797de46f8a55b5537abfe17",
"reference": "2c5f26cee466fabf5797de46f8a55b5537abfe17",
"shasum": ""
},
"require": {
"laravel/socialite": "*",
"php": ">=7.0.0."
},
"require-dev": {
"mockery/mockery": "^1.0",
"phpunit/phpunit": "^6.0"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Revolution\\Socialite\\Mastodon\\MastodonServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Revolution\\Socialite\\Mastodon\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "kawax",
"email": "kawaxbiz@gmail.com"
}
],
"description": "Socialite for Mastodon",
"keywords": [
"laravel",
"mastodon",
"socialite"
],
"time": "2018-05-10 03:45:17"
},
{ {
"name": "swiftmailer/swiftmailer", "name": "swiftmailer/swiftmailer",
"version": "v6.1.2", "version": "v6.1.2",

View File

@ -35,4 +35,12 @@ return [
'secret' => env('STRIPE_SECRET'), 'secret' => env('STRIPE_SECRET'),
], ],
'mastodon' => [
'domain' => env('MASTODON_DOMAIN'),
'client_id' => env('MASTODON_ID'),
'client_secret' => env('MASTODON_SECRET'),
'redirect' => env('MASTODON_REDIRECT'),
//'read', 'write', 'follow'
'scope' => ['read', 'write', 'follow'],
],
]; ];

View File

@ -44,7 +44,7 @@ return [
| |
*/ */
'encrypt' => false, 'encrypt' => true,
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

View File

@ -1,35 +0,0 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}

View File

@ -1,32 +0,0 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePasswordResetsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('password_resets', function (Blueprint $table) {
$table->string('email')->index();
$table->string('token');
$table->timestamp('created_at')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('password_resets');
}
}

View File

@ -0,0 +1,38 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateAppsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('apps', function (Blueprint $table) {
$table->increments('id');
$table->char('server');
$table->char('client_name');
$table->char('redirect_uris');
$table->char('scopes');
$table->char('website');
$table->char('response_id');
$table->char('client_id');
$table->char('client_secret');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('apps');
}
}

View File

@ -11,4 +11,16 @@
| |
*/ */
Route::get('/', 'TimelineController@show_timeline'); Route::get('/', function() {
return redirect()->route('public');
});
Route::get('/timeline/public', 'TimelineController@public_timeline')
->name('public');
Route::get('/timeline/friends', 'TimelineController@home_timeline')
->name('friends');
Route::get('/login', 'LoginController@login');
Route::get('/callback', 'LoginController@callback');