kopia lustrzana https://github.com/pixelfed/pixelfed
				
				
				
			Update routes and add RemoteAuthController
							rodzic
							
								
									0b90d629d5
								
							
						
					
					
						commit
						9cfa89dab4
					
				| 
						 | 
					@ -0,0 +1,568 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace App\Http\Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use Illuminate\Support\Str;
 | 
				
			||||||
 | 
					use Illuminate\Http\Request;
 | 
				
			||||||
 | 
					use App\Services\Account\RemoteAuthService;
 | 
				
			||||||
 | 
					use App\Models\RemoteAuth;
 | 
				
			||||||
 | 
					use App\Profile;
 | 
				
			||||||
 | 
					use App\User;
 | 
				
			||||||
 | 
					use Purify;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Auth;
 | 
				
			||||||
 | 
					use Illuminate\Support\Facades\Hash;
 | 
				
			||||||
 | 
					use Illuminate\Auth\Events\Registered;
 | 
				
			||||||
 | 
					use App\Util\Lexer\RestrictedNames;
 | 
				
			||||||
 | 
					use App\Services\EmailService;
 | 
				
			||||||
 | 
					use App\Services\MediaStorageService;
 | 
				
			||||||
 | 
					use App\Util\ActivityPub\Helpers;
 | 
				
			||||||
 | 
					use InvalidArgumentException;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class RemoteAuthController extends Controller
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public function start(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        abort_unless(config_cache('pixelfed.open_registration') && config('remote-auth.mastodon.enabled'), 404);
 | 
				
			||||||
 | 
					        if($request->user()) {
 | 
				
			||||||
 | 
					            return redirect('/');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return view('auth.remote.start');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function startRedirect(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return redirect('/login');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getAuthDomains(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(config('remote-auth.mastodon.domains.only_custom')) {
 | 
				
			||||||
 | 
					            $res = config('remote-auth.mastodon.domains.custom');
 | 
				
			||||||
 | 
					            if(!$res || !strlen($res)) {
 | 
				
			||||||
 | 
					                return [];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            $res = explode(',', $res);
 | 
				
			||||||
 | 
					            return response()->json($res);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $res = config('remote-auth.mastodon.domains.default');
 | 
				
			||||||
 | 
					        $res = explode(',', $res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return response()->json($res);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function redirect(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        abort_unless(config_cache('pixelfed.open_registration') && config('remote-auth.mastodon.enabled'), 404);
 | 
				
			||||||
 | 
					        $this->validate($request, ['domain' => 'required']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $domain = $request->input('domain');
 | 
				
			||||||
 | 
					        $compatible = RemoteAuthService::isDomainCompatible($domain);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!$compatible) {
 | 
				
			||||||
 | 
					            $res = [
 | 
				
			||||||
 | 
					                'domain' => $domain,
 | 
				
			||||||
 | 
					                'ready' => false,
 | 
				
			||||||
 | 
					                'action' => 'incompatible_domain'
 | 
				
			||||||
 | 
					            ];
 | 
				
			||||||
 | 
					            return response()->json($res);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(config('remote-auth.mastodon.domains.only_default')) {
 | 
				
			||||||
 | 
					            $defaultDomains = explode(',', config('remote-auth.mastodon.domains.default'));
 | 
				
			||||||
 | 
					            if(!in_array($domain, $defaultDomains)) {
 | 
				
			||||||
 | 
					                $res = [
 | 
				
			||||||
 | 
					                    'domain' => $domain,
 | 
				
			||||||
 | 
					                    'ready' => false,
 | 
				
			||||||
 | 
					                    'action' => 'incompatible_domain'
 | 
				
			||||||
 | 
					                ];
 | 
				
			||||||
 | 
					                return response()->json($res);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(config('remote-auth.mastodon.domains.only_custom') && config('remote-auth.mastodon.domains.custom')) {
 | 
				
			||||||
 | 
					            $customDomains = explode(',', config('remote-auth.mastodon.domains.custom'));
 | 
				
			||||||
 | 
					            if(!in_array($domain, $customDomains)) {
 | 
				
			||||||
 | 
					                $res = [
 | 
				
			||||||
 | 
					                    'domain' => $domain,
 | 
				
			||||||
 | 
					                    'ready' => false,
 | 
				
			||||||
 | 
					                    'action' => 'incompatible_domain'
 | 
				
			||||||
 | 
					                ];
 | 
				
			||||||
 | 
					                return response()->json($res);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $client = RemoteAuthService::getMastodonClient($domain);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        abort_unless($client, 422, 'Invalid mastodon client');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $request->session()->put('state', $state = Str::random(40));
 | 
				
			||||||
 | 
					        $request->session()->put('oauth_domain', $domain);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $query = http_build_query([
 | 
				
			||||||
 | 
					            'client_id' => $client->client_id,
 | 
				
			||||||
 | 
					            'redirect_uri' => $client->redirect_uri,
 | 
				
			||||||
 | 
					            'response_type' => 'code',
 | 
				
			||||||
 | 
					            'scope' => 'read',
 | 
				
			||||||
 | 
					            'state' => $state,
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $request->session()->put('oauth_redirect_to', 'https://' . $domain . '/oauth/authorize?' . $query);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $dsh = Str::random(17);
 | 
				
			||||||
 | 
					        $res = [
 | 
				
			||||||
 | 
					            'domain' => $domain,
 | 
				
			||||||
 | 
					            'ready' => true,
 | 
				
			||||||
 | 
					            'dsh' => $dsh
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return response()->json($res);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function preflight(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(!$request->filled('d') || !$request->filled('dsh') || !$request->session()->exists('oauth_redirect_to')) {
 | 
				
			||||||
 | 
					            return redirect('/login');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect()->away($request->session()->pull('oauth_redirect_to'));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function handleCallback(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $domain = $request->session()->get('oauth_domain');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if($request->filled('code')) {
 | 
				
			||||||
 | 
					            $code = $request->input('code');
 | 
				
			||||||
 | 
					            $state = $request->session()->pull('state');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            throw_unless(
 | 
				
			||||||
 | 
					                strlen($state) > 0 && $state === $request->state,
 | 
				
			||||||
 | 
					                InvalidArgumentException::class,
 | 
				
			||||||
 | 
					                'Invalid state value.'
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $res = RemoteAuthService::getToken($domain, $code);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(!$res || !isset($res['access_token'])) {
 | 
				
			||||||
 | 
					                $request->session()->regenerate();
 | 
				
			||||||
 | 
					                return redirect('/login');
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            $request->session()->put('oauth_remote_session_token', $res['access_token']);
 | 
				
			||||||
 | 
					            return redirect('/auth/mastodon/getting-started');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return redirect('/login');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function onboarding(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        abort_unless(config_cache('pixelfed.open_registration') && config('remote-auth.mastodon.enabled'), 404);
 | 
				
			||||||
 | 
					        if($request->user()) {
 | 
				
			||||||
 | 
					            return redirect('/');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return view('auth.remote.onboarding');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function sessionCheck(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        abort_if($request->user(), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_domain'), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_remote_session_token'), 403);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $domain = $request->session()->get('oauth_domain');
 | 
				
			||||||
 | 
					        $token = $request->session()->get('oauth_remote_session_token');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $res = RemoteAuthService::getVerifyCredentials($domain, $token);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        abort_if(!$res || !isset($res['acct']), 403, 'Invalid credentials');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $webfinger = strtolower('@' . $res['acct'] . '@' . $domain);
 | 
				
			||||||
 | 
					        $request->session()->put('oauth_masto_webfinger', $webfinger);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(config('remote-auth.mastodon.max_uses.enabled')) {
 | 
				
			||||||
 | 
					            $limit = config('remote-auth.mastodon.max_uses.limit');
 | 
				
			||||||
 | 
					            $uses = RemoteAuthService::lookupWebfingerUses($webfinger);
 | 
				
			||||||
 | 
					            if($uses >= $limit) {
 | 
				
			||||||
 | 
					                return response()->json([
 | 
				
			||||||
 | 
					                    'code' => 200,
 | 
				
			||||||
 | 
					                    'msg' => 'Success!',
 | 
				
			||||||
 | 
					                    'action' => 'max_uses_reached'
 | 
				
			||||||
 | 
					                ]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $exists = RemoteAuth::whereDomain($domain)->where('webfinger', $webfinger)->whereNotNull('user_id')->first();
 | 
				
			||||||
 | 
					        if($exists && $exists->user_id) {
 | 
				
			||||||
 | 
					            return response()->json([
 | 
				
			||||||
 | 
					                'code' => 200,
 | 
				
			||||||
 | 
					                'msg' => 'Success!',
 | 
				
			||||||
 | 
					                'action' => 'redirect_existing_user'
 | 
				
			||||||
 | 
					            ]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return response()->json([
 | 
				
			||||||
 | 
					            'code' => 200,
 | 
				
			||||||
 | 
					            'msg' => 'Success!',
 | 
				
			||||||
 | 
					            'action' => 'onboard'
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function sessionGetMastodonData(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        abort_if($request->user(), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_domain'), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_remote_session_token'), 403);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $domain = $request->session()->get('oauth_domain');
 | 
				
			||||||
 | 
					        $token = $request->session()->get('oauth_remote_session_token');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $res = RemoteAuthService::getVerifyCredentials($domain, $token);
 | 
				
			||||||
 | 
					        $res['_webfinger'] = strtolower('@' . $res['acct'] . '@' . $domain);
 | 
				
			||||||
 | 
					        $res['_domain'] = strtolower($domain);
 | 
				
			||||||
 | 
					        $request->session()->put('oauth_remasto_id', $res['id']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $ra = RemoteAuth::updateOrCreate([
 | 
				
			||||||
 | 
					            'domain' => $domain,
 | 
				
			||||||
 | 
					            'webfinger' => $res['_webfinger'],
 | 
				
			||||||
 | 
					        ], [
 | 
				
			||||||
 | 
					            'software' => 'mastodon',
 | 
				
			||||||
 | 
					            'ip_address' => $request->ip(),
 | 
				
			||||||
 | 
					            'bearer_token' => $token,
 | 
				
			||||||
 | 
					            'verify_credentials' => $res,
 | 
				
			||||||
 | 
					            'last_verify_credentials_at' => now(),
 | 
				
			||||||
 | 
					            'last_successful_login_at' => now()
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $request->session()->put('oauth_masto_raid', $ra->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return response()->json($res);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function sessionValidateUsername(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        abort_if($request->user(), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_domain'), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_remote_session_token'), 403);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->validate($request, [
 | 
				
			||||||
 | 
					            'username' => [
 | 
				
			||||||
 | 
					                'required',
 | 
				
			||||||
 | 
					                'min:2',
 | 
				
			||||||
 | 
					                'max:15',
 | 
				
			||||||
 | 
					                function ($attribute, $value, $fail) {
 | 
				
			||||||
 | 
					                    $dash = substr_count($value, '-');
 | 
				
			||||||
 | 
					                    $underscore = substr_count($value, '_');
 | 
				
			||||||
 | 
					                    $period = substr_count($value, '.');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if(ends_with($value, ['.php', '.js', '.css'])) {
 | 
				
			||||||
 | 
					                        return $fail('Username is invalid.');
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if(($dash + $underscore + $period) > 1) {
 | 
				
			||||||
 | 
					                        return $fail('Username is invalid. Can only contain one dash (-), period (.) or underscore (_).');
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (!ctype_alnum($value[0])) {
 | 
				
			||||||
 | 
					                        return $fail('Username is invalid. Must start with a letter or number.');
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (!ctype_alnum($value[strlen($value) - 1])) {
 | 
				
			||||||
 | 
					                        return $fail('Username is invalid. Must end with a letter or number.');
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    $val = str_replace(['_', '.', '-'], '', $value);
 | 
				
			||||||
 | 
					                    if(!ctype_alnum($val)) {
 | 
				
			||||||
 | 
					                        return $fail('Username is invalid. Username must be alpha-numeric and may contain dashes (-), periods (.) and underscores (_).');
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    $restricted = RestrictedNames::get();
 | 
				
			||||||
 | 
					                    if (in_array(strtolower($value), array_map('strtolower', $restricted))) {
 | 
				
			||||||
 | 
					                        return $fail('Username cannot be used.');
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					        $username = strtolower($request->input('username'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $exists = User::where('username', $username)->exists();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return response()->json([
 | 
				
			||||||
 | 
					            'code' => 200,
 | 
				
			||||||
 | 
					            'username' => $username,
 | 
				
			||||||
 | 
					            'exists' => $exists
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function sessionValidateEmail(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        abort_if($request->user(), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_domain'), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_remote_session_token'), 403);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->validate($request, [
 | 
				
			||||||
 | 
					            'email' => [
 | 
				
			||||||
 | 
					                'required',
 | 
				
			||||||
 | 
					                'email:strict,filter_unicode,dns,spoof',
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $email = $request->input('email');
 | 
				
			||||||
 | 
					        $banned = EmailService::isBanned($email);
 | 
				
			||||||
 | 
					        $exists = User::where('email', $email)->exists();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return response()->json([
 | 
				
			||||||
 | 
					            'code' => 200,
 | 
				
			||||||
 | 
					            'email' => $email,
 | 
				
			||||||
 | 
					            'exists' => $exists,
 | 
				
			||||||
 | 
					            'banned' => $banned
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function sessionGetMastodonFollowers(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_domain'), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_remote_session_token'), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_remasto_id'), 403);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $domain = $request->session()->get('oauth_domain');
 | 
				
			||||||
 | 
					        $token = $request->session()->get('oauth_remote_session_token');
 | 
				
			||||||
 | 
					        $id = $request->session()->get('oauth_remasto_id');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $res = RemoteAuthService::getFollowing($domain, $token, $id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!$res) {
 | 
				
			||||||
 | 
					            return response()->json([
 | 
				
			||||||
 | 
					                'code' => 200,
 | 
				
			||||||
 | 
					                'following' => []
 | 
				
			||||||
 | 
					            ]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $res = collect($res)->filter(fn($acct) => Helpers::validateUrl($acct['url']))->values()->toArray();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return response()->json([
 | 
				
			||||||
 | 
					            'code' => 200,
 | 
				
			||||||
 | 
					            'following' => $res
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function handleSubmit(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_domain'), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_remote_session_token'), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_remasto_id'), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_masto_webfinger'), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_masto_raid'), 403);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->validate($request, [
 | 
				
			||||||
 | 
					            'email' => 'required|email:strict,filter_unicode,dns,spoof',
 | 
				
			||||||
 | 
					            'username' => [
 | 
				
			||||||
 | 
					                'required',
 | 
				
			||||||
 | 
					                'min:2',
 | 
				
			||||||
 | 
					                'max:15',
 | 
				
			||||||
 | 
					                'unique:users,username',
 | 
				
			||||||
 | 
					                function ($attribute, $value, $fail) {
 | 
				
			||||||
 | 
					                    $dash = substr_count($value, '-');
 | 
				
			||||||
 | 
					                    $underscore = substr_count($value, '_');
 | 
				
			||||||
 | 
					                    $period = substr_count($value, '.');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if(ends_with($value, ['.php', '.js', '.css'])) {
 | 
				
			||||||
 | 
					                        return $fail('Username is invalid.');
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if(($dash + $underscore + $period) > 1) {
 | 
				
			||||||
 | 
					                        return $fail('Username is invalid. Can only contain one dash (-), period (.) or underscore (_).');
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (!ctype_alnum($value[0])) {
 | 
				
			||||||
 | 
					                        return $fail('Username is invalid. Must start with a letter or number.');
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (!ctype_alnum($value[strlen($value) - 1])) {
 | 
				
			||||||
 | 
					                        return $fail('Username is invalid. Must end with a letter or number.');
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    $val = str_replace(['_', '.', '-'], '', $value);
 | 
				
			||||||
 | 
					                    if(!ctype_alnum($val)) {
 | 
				
			||||||
 | 
					                        return $fail('Username is invalid. Username must be alpha-numeric and may contain dashes (-), periods (.) and underscores (_).');
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    $restricted = RestrictedNames::get();
 | 
				
			||||||
 | 
					                    if (in_array(strtolower($value), array_map('strtolower', $restricted))) {
 | 
				
			||||||
 | 
					                        return $fail('Username cannot be used.');
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					            'password' => 'required|string|min:8|confirmed',
 | 
				
			||||||
 | 
					            'name' => 'nullable|max:30'
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $email = $request->input('email');
 | 
				
			||||||
 | 
					        $username = $request->input('username');
 | 
				
			||||||
 | 
					        $password = $request->input('password');
 | 
				
			||||||
 | 
					        $name = $request->input('name');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $user = $this->createUser([
 | 
				
			||||||
 | 
					            'name' => $name,
 | 
				
			||||||
 | 
					            'username' => $username,
 | 
				
			||||||
 | 
					            'password' => $password,
 | 
				
			||||||
 | 
					            'email' => $email
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $raid = $request->session()->pull('oauth_masto_raid');
 | 
				
			||||||
 | 
					        $webfinger = $request->session()->pull('oauth_masto_webfinger');
 | 
				
			||||||
 | 
					        $token = $user->createToken('Onboarding')->accessToken;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $ra = RemoteAuth::where('id', $raid)->where('webfinger', $webfinger)->firstOrFail();
 | 
				
			||||||
 | 
					        $ra->user_id = $user->id;
 | 
				
			||||||
 | 
					        $ra->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            'code' => 200,
 | 
				
			||||||
 | 
					            'msg' => 'Success',
 | 
				
			||||||
 | 
					            'token' => $token
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function storeBio(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        abort_unless(config_cache('pixelfed.open_registration') && config('remote-auth.mastodon.enabled'), 404);
 | 
				
			||||||
 | 
					        abort_unless($request->user(), 404);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_domain'), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_remote_session_token'), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_remasto_id'), 403);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->validate($request, [
 | 
				
			||||||
 | 
					            'bio' => 'required|nullable|max:500',
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $profile = $request->user()->profile;
 | 
				
			||||||
 | 
					        $profile->bio = Purify::clean($request->input('bio'));
 | 
				
			||||||
 | 
					        $profile->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return [200];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function accountToId(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        abort_unless(config_cache('pixelfed.open_registration') && config('remote-auth.mastodon.enabled'), 404);
 | 
				
			||||||
 | 
					        abort_if($request->user(), 404);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_domain'), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_remote_session_token'), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_remasto_id'), 403);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->validate($request, [
 | 
				
			||||||
 | 
					            'account' => 'required|url'
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $account = $request->input('account');
 | 
				
			||||||
 | 
					        abort_unless(substr(strtolower($account), 0, 8) === 'https://', 404);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $host = strtolower(config('pixelfed.domain.app'));
 | 
				
			||||||
 | 
					        $domain = strtolower(parse_url($account, PHP_URL_HOST));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if($domain == $host) {
 | 
				
			||||||
 | 
					            $username = Str::of($account)->explode('/')->last();
 | 
				
			||||||
 | 
					            $user = User::where('username', $username)->first();
 | 
				
			||||||
 | 
					            if($user) {
 | 
				
			||||||
 | 
					                return ['id' => (string) $user->profile_id];
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                return [];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                $profile = Helpers::profileFetch($account);
 | 
				
			||||||
 | 
					                if($profile) {
 | 
				
			||||||
 | 
					                    return ['id' => (string) $profile->id];
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    return [];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } catch (\GuzzleHttp\Exception\RequestException $e) {
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            } catch (Exception $e) {
 | 
				
			||||||
 | 
					                return [];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function storeAvatar(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        abort_unless(config_cache('pixelfed.open_registration') && config('remote-auth.mastodon.enabled'), 404);
 | 
				
			||||||
 | 
					        abort_unless($request->user(), 404);
 | 
				
			||||||
 | 
					        $this->validate($request, [
 | 
				
			||||||
 | 
					            'avatar_url' => 'required|active_url',
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $user = $request->user();
 | 
				
			||||||
 | 
					        $profile = $user->profile;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        abort_if(!$profile->avatar, 404, 'Missing avatar');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $avatar = $profile->avatar;
 | 
				
			||||||
 | 
					        $avatar->remote_url = $request->input('avatar_url');
 | 
				
			||||||
 | 
					        $avatar->save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        MediaStorageService::avatar($avatar, config_cache('pixelfed.cloud_storage') == false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return [200];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function finishUp(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        abort_unless(config_cache('pixelfed.open_registration') && config('remote-auth.mastodon.enabled'), 404);
 | 
				
			||||||
 | 
					        abort_unless($request->user(), 404);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $currentWebfinger = '@' . $request->user()->username . '@' . config('pixelfed.domain.app');
 | 
				
			||||||
 | 
					        $ra = RemoteAuth::where('user_id', $request->user()->id)->firstOrFail();
 | 
				
			||||||
 | 
					        RemoteAuthService::submitToBeagle(
 | 
				
			||||||
 | 
					            $ra->webfinger,
 | 
				
			||||||
 | 
					            $ra->verify_credentials['url'],
 | 
				
			||||||
 | 
					            $currentWebfinger,
 | 
				
			||||||
 | 
					            $request->user()->url()
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return [200];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function handleLogin(Request $request)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        abort_unless(config_cache('pixelfed.open_registration') && config('remote-auth.mastodon.enabled'), 404);
 | 
				
			||||||
 | 
					        abort_if($request->user(), 404);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_domain'), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_remote_session_token'), 403);
 | 
				
			||||||
 | 
					        abort_unless($request->session()->exists('oauth_masto_webfinger'), 403);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $domain = $request->session()->get('oauth_domain');
 | 
				
			||||||
 | 
					        $wf = $request->session()->get('oauth_masto_webfinger');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $ra = RemoteAuth::where('webfinger', $wf)->where('domain', $domain)->whereNotNull('user_id')->firstOrFail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $user = User::findOrFail($ra->user_id);
 | 
				
			||||||
 | 
					        abort_if($user->is_admin || $user->status != null, 422, 'Invalid auth action');
 | 
				
			||||||
 | 
					        Auth::loginUsingId($ra->user_id);
 | 
				
			||||||
 | 
					        return [200];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected function createUser($data)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        event(new Registered($user = User::create([
 | 
				
			||||||
 | 
					            'name'     => Purify::clean($data['name']),
 | 
				
			||||||
 | 
					            'username' => $data['username'],
 | 
				
			||||||
 | 
					            'email'    => $data['email'],
 | 
				
			||||||
 | 
					            'password' => Hash::make($data['password']),
 | 
				
			||||||
 | 
					            'email_verified_at' => config('remote-auth.mastodon.contraints.skip_email_verification') ? now() : null,
 | 
				
			||||||
 | 
					            'app_register_ip' => request()->ip(),
 | 
				
			||||||
 | 
					            'register_source' => 'mastodon'
 | 
				
			||||||
 | 
					        ])));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $this->guarder()->login($user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $user;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected function guarder()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return Auth::guard();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,7 @@ return [
 | 
				
			||||||
             *
 | 
					             *
 | 
				
			||||||
             *   Allow Sign-in with Mastodon using only the default domains
 | 
					             *   Allow Sign-in with Mastodon using only the default domains
 | 
				
			||||||
             */
 | 
					             */
 | 
				
			||||||
            'only_default' => env('PF_LOGIN_WITH_MASTODON_ONLY_DEFAULT', true),
 | 
					            'only_default' => env('PF_LOGIN_WITH_MASTODON_ONLY_DEFAULT', false),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /*
 | 
					            /*
 | 
				
			||||||
             *   Use only custom domains
 | 
					             *   Use only custom domains
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,11 +22,11 @@
 | 
				
			||||||
                        type="button"
 | 
					                        type="button"
 | 
				
			||||||
                        class="server-btn"
 | 
					                        class="server-btn"
 | 
				
			||||||
                        @click="handleRedirect(domain)">
 | 
					                        @click="handleRedirect(domain)">
 | 
				
			||||||
                        Sign-in with <span class="font-weight-bold">{{ domain }}</span>
 | 
					                        <span class="font-weight-bold">{{ domain }}</span>
 | 
				
			||||||
                    </button>
 | 
					                    </button>
 | 
				
			||||||
                    <hr>
 | 
					                    <hr>
 | 
				
			||||||
                    <p class="text-center">
 | 
					                    <p class="text-center">
 | 
				
			||||||
                        <button type="button" class="other-server-btn">Sign-in with a different server</button>
 | 
					                        <button type="button" class="other-server-btn" @click="handleOther()">Sign-in with a different server</button>
 | 
				
			||||||
                    </p>
 | 
					                    </p>
 | 
				
			||||||
                    <div class="w-100">
 | 
					                    <div class="w-100">
 | 
				
			||||||
                        <hr>
 | 
					                        <hr>
 | 
				
			||||||
| 
						 | 
					@ -83,6 +83,26 @@
 | 
				
			||||||
                        window.location.href = '/auth/raw/mastodon/preflight?d=' + domain + '&dsh=' + res.data.dsh;
 | 
					                        window.location.href = '/auth/raw/mastodon/preflight?d=' + domain + '&dsh=' + res.data.dsh;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            handleOther() {
 | 
				
			||||||
 | 
					                swal({
 | 
				
			||||||
 | 
					                  text: 'Enter your mastodon domain (without https://)',
 | 
				
			||||||
 | 
					                  content: "input",
 | 
				
			||||||
 | 
					                  button: {
 | 
				
			||||||
 | 
					                    text: "Next",
 | 
				
			||||||
 | 
					                    closeModal: false,
 | 
				
			||||||
 | 
					                  },
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .then(domain => {
 | 
				
			||||||
 | 
					                  if (!domain) throw null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                  if(domain.startsWith('https://')) {
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                  return this.handleRedirect(domain);
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,7 @@
 | 
				
			||||||
                            <div class="col-md-12">
 | 
					                            <div class="col-md-12">
 | 
				
			||||||
                                <div class="checkbox">
 | 
					                                <div class="checkbox">
 | 
				
			||||||
                                    <label>
 | 
					                                    <label>
 | 
				
			||||||
                                        <input type="checkbox" name="remember" {{ old('remember') ? 'checked' : '' }}> 
 | 
					                                        <input type="checkbox" name="remember" {{ old('remember') ? 'checked' : '' }}>
 | 
				
			||||||
                                        <span class="font-weight-bold ml-1 text-muted">
 | 
					                                        <span class="font-weight-bold ml-1 text-muted">
 | 
				
			||||||
                                            {{ __('Remember Me') }}
 | 
					                                            {{ __('Remember Me') }}
 | 
				
			||||||
                                        </span>
 | 
					                                        </span>
 | 
				
			||||||
| 
						 | 
					@ -64,7 +64,7 @@
 | 
				
			||||||
	                        </div>
 | 
						                        </div>
 | 
				
			||||||
                        @endif
 | 
					                        @endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        <div class="form-group row mb-0">
 | 
					                        <div class="form-group row mb-4">
 | 
				
			||||||
                            <div class="col-md-12">
 | 
					                            <div class="col-md-12">
 | 
				
			||||||
                                <button type="submit" class="btn btn-primary btn-block btn-lg font-weight-bold">
 | 
					                                <button type="submit" class="btn btn-primary btn-block btn-lg font-weight-bold">
 | 
				
			||||||
                                    {{ __('Login') }}
 | 
					                                    {{ __('Login') }}
 | 
				
			||||||
| 
						 | 
					@ -72,7 +72,21 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            </div>
 | 
					                            </div>
 | 
				
			||||||
                        </div>
 | 
					                        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    </form>
 | 
					                    </form>
 | 
				
			||||||
 | 
					                    @if(config_cache('pixelfed.open_registration') && config('remote-auth.mastodon.enabled'))
 | 
				
			||||||
 | 
					                    <hr>
 | 
				
			||||||
 | 
					                    <form method="POST" action="/auth/raw/mastodon/start">
 | 
				
			||||||
 | 
					                        @csrf
 | 
				
			||||||
 | 
					                        <div class="form-group row mb-0">
 | 
				
			||||||
 | 
					                            <div class="col-md-12">
 | 
				
			||||||
 | 
					                                <button type="submit" class="btn btn-primary btn-sm btn-block rounded-pill font-weight-bold" style="background: linear-gradient(#6364FF, #563ACC);">
 | 
				
			||||||
 | 
					                                    Sign-in with Mastodon
 | 
				
			||||||
 | 
					                                </button>
 | 
				
			||||||
 | 
					                            </div>
 | 
				
			||||||
 | 
					                        </div>
 | 
				
			||||||
 | 
					                    </form>
 | 
				
			||||||
 | 
					                    @endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <hr>
 | 
					                    <hr>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -174,6 +174,25 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
 | 
				
			||||||
	Route::get('web/explore', 'LandingController@exploreRedirect');
 | 
						Route::get('web/explore', 'LandingController@exploreRedirect');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Auth::routes();
 | 
						Auth::routes();
 | 
				
			||||||
 | 
					    Route::get('auth/raw/mastodon/start', 'RemoteAuthController@startRedirect');
 | 
				
			||||||
 | 
					    Route::post('auth/raw/mastodon/config', 'RemoteAuthController@getConfig');
 | 
				
			||||||
 | 
					    Route::post('auth/raw/mastodon/domains', 'RemoteAuthController@getAuthDomains');
 | 
				
			||||||
 | 
					    Route::post('auth/raw/mastodon/start', 'RemoteAuthController@start');
 | 
				
			||||||
 | 
					    Route::post('auth/raw/mastodon/redirect', 'RemoteAuthController@redirect');
 | 
				
			||||||
 | 
					    Route::get('auth/raw/mastodon/preflight', 'RemoteAuthController@preflight');
 | 
				
			||||||
 | 
					    Route::get('auth/mastodon/callback', 'RemoteAuthController@handleCallback');
 | 
				
			||||||
 | 
					    Route::get('auth/mastodon/getting-started', 'RemoteAuthController@onboarding');
 | 
				
			||||||
 | 
					    Route::post('auth/raw/mastodon/s/check', 'RemoteAuthController@sessionCheck');
 | 
				
			||||||
 | 
					    Route::post('auth/raw/mastodon/s/prefill', 'RemoteAuthController@sessionGetMastodonData');
 | 
				
			||||||
 | 
					    Route::post('auth/raw/mastodon/s/username-check', 'RemoteAuthController@sessionValidateUsername');
 | 
				
			||||||
 | 
					    Route::post('auth/raw/mastodon/s/email-check', 'RemoteAuthController@sessionValidateEmail');
 | 
				
			||||||
 | 
					    Route::post('auth/raw/mastodon/s/following', 'RemoteAuthController@sessionGetMastodonFollowers');
 | 
				
			||||||
 | 
					    Route::post('auth/raw/mastodon/s/submit', 'RemoteAuthController@handleSubmit');
 | 
				
			||||||
 | 
					    Route::post('auth/raw/mastodon/s/store-bio', 'RemoteAuthController@storeBio');
 | 
				
			||||||
 | 
					    Route::post('auth/raw/mastodon/s/store-avatar', 'RemoteAuthController@storeAvatar');
 | 
				
			||||||
 | 
					    Route::post('auth/raw/mastodon/s/account-to-id', 'RemoteAuthController@accountToId');
 | 
				
			||||||
 | 
					    Route::post('auth/raw/mastodon/s/finish-up', 'RemoteAuthController@finishUp');
 | 
				
			||||||
 | 
					    Route::post('auth/raw/mastodon/s/login', 'RemoteAuthController@handleLogin');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Route::get('discover', 'DiscoverController@home')->name('discover');
 | 
						Route::get('discover', 'DiscoverController@home')->name('discover');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,6 +37,7 @@ mix.js('resources/assets/js/app.js', 'public/js')
 | 
				
			||||||
.js('resources/assets/js/account-import.js', 'public/js')
 | 
					.js('resources/assets/js/account-import.js', 'public/js')
 | 
				
			||||||
.js('resources/assets/js/admin_invite.js', 'public/js')
 | 
					.js('resources/assets/js/admin_invite.js', 'public/js')
 | 
				
			||||||
.js('resources/assets/js/landing.js', 'public/js')
 | 
					.js('resources/assets/js/landing.js', 'public/js')
 | 
				
			||||||
 | 
					.js('resources/assets/js/remote_auth.js', 'public/js')
 | 
				
			||||||
.vue({ version: 2 });
 | 
					.vue({ version: 2 });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mix.extract();
 | 
					mix.extract();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Ładowanie…
	
		Reference in New Issue