diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index 1587f219..ecde126f 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -23,11 +23,11 @@ namespace Poniverse\Ponyfm\Http\Controllers; use Carbon\Carbon; use Illuminate\Support\Facades\Input; use League\OAuth2\Client\Provider\Exception\IdentityProviderException; +use League\OAuth2\Client\Token\AccessToken; use Log; use Poniverse\Lib\Client; use Poniverse\Ponyfm\Models\User; use Auth; -use Config; use DB; use Request; use Redirect; @@ -117,6 +117,38 @@ class AuthController extends Controller return $this->loginRedirect($user); } + + /** + * Processes requests to update a user's Poniverse information. + * + * @return \Illuminate\Http\JsonResponse + */ + public function postPoniverseAccountSync() + { + $poniverseId = Input::get('id'); + $updatedAttribute = Input::get('attribute'); + + // Only email address updates are supported at this time. + if ('email' !== $updatedAttribute) { + return \Response::json(['message' => 'Unsupported Poniverse account attribute.'], 400); + } + + $user = User::wherePoniverseId($poniverseId)->first(); + /** @var AccessToken $accessToken */ + $accessToken = $user->getAccessToken(); + + if ($accessToken->hasExpired()) { + $accessToken = $this->poniverse->getOAuthProvider()->getAccessToken('refresh_token', ['refresh_token' => $accessToken->getRefreshToken()]); + $user->setAccessToken($accessToken); + } + + /** @var \Poniverse\Lib\Entity\Poniverse\User $newUserData */ + $newUserData = $this->poniverse->getOAuthProvider()->getResourceOwner($accessToken); + + $user->{$updatedAttribute} = $newUserData->{$updatedAttribute}; + $user->save(); + + return \Response::json(['message' => 'Successfully updated this user!'], 200); } protected function loginRedirect($user, $rememberMe = true) diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 1192798c..39449569 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -53,11 +53,9 @@ class Kernel extends HttpKernel protected $routeMiddleware = [ 'auth' => \Poniverse\Ponyfm\Http\Middleware\Authenticate::class, 'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class, - 'can' => \Illuminate\Auth\Middleware\Authorize::class, 'auth.oauth' => \Poniverse\Ponyfm\Http\Middleware\AuthenticateOAuth::class, 'can' => \Poniverse\Ponyfm\Http\Middleware\Authorize::class, 'json-exceptions' => \Poniverse\Ponyfm\Http\Middleware\JsonExceptions::class, - //'can' => \Illuminate\Foundation\Http\Middleware\Authorize::class, 'guest' => \Poniverse\Ponyfm\Http\Middleware\RedirectIfAuthenticated::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, ]; diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php index ed883077..3aaa7648 100644 --- a/app/Http/Middleware/VerifyCsrfToken.php +++ b/app/Http/Middleware/VerifyCsrfToken.php @@ -30,6 +30,7 @@ class VerifyCsrfToken extends BaseVerifier * @var array */ protected $except = [ - 'api/*' + 'api/*', + 'auth/poniverse-sync' ]; } diff --git a/app/Models/User.php b/app/Models/User.php index 360e3d3a..27cb8d04 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -32,6 +32,7 @@ use Illuminate\Database\Eloquent\Relations\MorphMany; use Illuminate\Foundation\Auth\Access\Authorizable; use Auth; use Illuminate\Support\Str; +use League\OAuth2\Client\Token\AccessToken; use Poniverse\Ponyfm\Contracts\Commentable; use Poniverse\Ponyfm\Contracts\Searchable; use Poniverse\Ponyfm\Traits\IndexedInElasticsearchTrait; @@ -95,6 +96,7 @@ use Venturecraft\Revisionable\RevisionableTrait; * @method static \Illuminate\Database\Query\Builder|\Poniverse\Ponyfm\Models\User whereDisabledAt($value) * @method static \Illuminate\Database\Query\Builder|\Poniverse\Ponyfm\Models\User withEmailSubscriptionFor($activityType) * @mixin \Eloquent + * @method static \Illuminate\Database\Query\Builder|\Poniverse\Ponyfm\Models\User wherePoniverseId($poniverseId) */ class User extends Model implements AuthenticatableContract, CanResetPasswordContract, \Illuminate\Contracts\Auth\Access\Authorizable, Searchable, Commentable { @@ -142,6 +144,51 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon }); } + /** + * Finds a user by their Poniverse account ID. + * + * @param $query + * @param int $poniverseId + * @return mixed + */ + public function scopeWherePoniverseId($query, int $poniverseId) { + return $query + ->join('oauth2_tokens', 'users.id', '=', 'oauth2_tokens.user_id') + ->select('users.*', 'oauth2_tokens.external_user_id') + ->where('oauth2_tokens.external_user_id', '=', $poniverseId); + } + + /** + * Gets this user's OAuth access token record. + * + * @return AccessToken + */ + public function getAccessToken():AccessToken { + $accessTokenRecord = DB::table('oauth2_tokens')->where('user_id', '=', $this->id)->first(); + return new AccessToken([ + 'access_token' => $accessTokenRecord->access_token, + 'refresh_token' => $accessTokenRecord->refresh_token, + 'expires' => $accessTokenRecord->expires, + 'resource_owner_id' => $accessTokenRecord->external_user_id, + ]); + } + + /** + * Updates this user's access token record. + * + * @param AccessToken $accessToken + */ + public function setAccessToken(AccessToken $accessToken) { + DB::table('oauth2_tokens') + ->where('user_id', '=', $this->id) + ->update([ + 'access_token' => $accessToken->getToken(), + 'refresh_token' => $accessToken->getRefreshToken(), + 'expires' => $accessToken->getExpires(), + 'resource_owner_id' => $accessToken->getResourceOwnerId(), + ]); + } + /** * Takes the given string, slugifies it, and increments a counter if needed * to generate a unique slug version of it. diff --git a/routes/web.php b/routes/web.php index 0deb5137..53d63d0c 100644 --- a/routes/web.php +++ b/routes/web.php @@ -54,6 +54,7 @@ Route::get('/register', 'AccountController@getRegister'); Route::get('/login', 'AuthController@getLogin'); Route::post('/auth/logout', 'AuthController@postLogout'); Route::get('/auth/oauth', 'AuthController@getOAuth'); +Route::post('/auth/poniverse-sync', 'AuthController@postPoniverseAccountSync')->middleware('throttle:60,1'); Route::get('/about', function () { return View::make('pages.about');