diff --git a/framework/core/ember/app/adapters/application.js b/framework/core/ember/app/adapters/application.js index d97628295..595489cbd 100644 --- a/framework/core/ember/app/adapters/application.js +++ b/framework/core/ember/app/adapters/application.js @@ -25,12 +25,17 @@ export default JsonApiAdapter.extend({ // If it's a server error, show an alert message. The alerts controller // has been injected into this adapter. if (errors instanceof JsonApiAdapter.ServerError) { - var message = AlertMessage.create({ + var message; + if (errors.status === 401) { + message = 'You don\'t have permission to do this.'; + } else { + message = errors.message; + } + var alert = AlertMessage.create({ type: 'warning', - message: 'Something went wrong: '+errors.message.errors[0].code + message: message }); - this.get('alerts').send('alert', message); - return; + this.get('alerts').send('alert', alert); } return errors; diff --git a/framework/core/ember/app/controllers/discussion.js b/framework/core/ember/app/controllers/discussion.js index f0c593846..6c3357e53 100644 --- a/framework/core/ember/app/controllers/discussion.js +++ b/framework/core/ember/app/controllers/discussion.js @@ -76,15 +76,19 @@ export default Ember.Controller.extend(Ember.Evented, UseComposerMixin, { reply: function() { var discussion = this.get('model'); var controller = this; - this.showComposer(function() { - return ComposerReply.create({ - user: controller.get('session.user'), - discussion: discussion, - submit: function(data) { - controller.saveReply(discussion, data); - } + if (this.get('session.isAuthenticated')) { + this.showComposer(function() { + return ComposerReply.create({ + user: controller.get('session.user'), + discussion: discussion, + submit: function(data) { + controller.saveReply(discussion, data); + } + }); }); - }); + } else { + this.send('signup'); + } }, // This action is called when the start position of the discussion diff --git a/framework/core/ember/app/controllers/index.js b/framework/core/ember/app/controllers/index.js index c3986e195..cd6ca95ec 100644 --- a/framework/core/ember/app/controllers/index.js +++ b/framework/core/ember/app/controllers/index.js @@ -24,8 +24,10 @@ export default Ember.Controller.extend(UseComposer, Paneable, { var controller = this; return this.saveAndDismissComposer(discussion).then(function(discussion) { - controller.get('index').send('loadResults'); - controller.transitionToRoute('discussion', discussion); + if (discussion) { + controller.get('index').send('loadResults'); + controller.transitionToRoute('discussion', discussion); + } }); }, @@ -46,14 +48,18 @@ export default Ember.Controller.extend(UseComposer, Paneable, { newDiscussion: function() { var controller = this; - this.showComposer(function() { - return ComposerDiscussion.create({ - user: controller.get('session.user'), - submit: function(data) { - controller.saveDiscussion(data); - } + if (this.get('session.isAuthenticated')) { + this.showComposer(function() { + return ComposerDiscussion.create({ + user: controller.get('session.user'), + submit: function(data) { + controller.saveDiscussion(data); + } + }); }); - }); + } else { + this.send('signup'); + } }, discussionRemoved: function(discussion) { diff --git a/framework/core/ember/app/views/discussion.js b/framework/core/ember/app/views/discussion.js index ebe2802f0..0c5e3ac8d 100644 --- a/framework/core/ember/app/views/discussion.js +++ b/framework/core/ember/app/views/discussion.js @@ -62,7 +62,7 @@ export default Ember.View.extend(HasItemLists, { populateControls: function(items) { var view = this; - this.addActionItem(items, 'reply', 'Reply', 'reply', 'discussion.canReply', function() { + this.addActionItem(items, 'reply', 'Reply', 'reply', null, function() { view.get('streamContent').send('goToLast'); view.get('controller').send('reply'); }); diff --git a/framework/core/src/Api/Actions/BaseAction.php b/framework/core/src/Api/Actions/BaseAction.php index ee6b617c4..016925498 100644 --- a/framework/core/src/Api/Actions/BaseAction.php +++ b/framework/core/src/Api/Actions/BaseAction.php @@ -23,8 +23,6 @@ abstract class BaseAction extends Action public function handle(Request $request, $routeParams = []) { - $this->registerErrorHandlers(); // @todo convert to middleware and add to route group? - $params = array_merge($request->all(), $routeParams); return $this->call($params); @@ -87,31 +85,6 @@ abstract class BaseAction extends Action return $this->respondWithArray($document->toArray(), $statusCode, $headers); } - protected function registerErrorHandlers() - { - // if (! Config::get('app.debug')) { - // App::error(function ($exception, $code) { - // return $this->respondWithError('ApplicationError', $code); - // }); - // } - - // App::error(function (ModelNotFoundException $exception) { - // return $this->respondWithError('ResourceNotFound', 404); - // }); - - // App::error(function (ValidationFailureException $exception) { - // $errors = []; - // foreach ($exception->getErrors()->getMessages() as $field => $messages) { - // $errors[] = [ - // 'code' => 'ValidationFailure', - // 'detail' => implode("\n", $messages), - // 'path' => $field - // ]; - // } - // return $this->respondWithErrors($errors, 422); - // }); - } - protected function respondWithErrors($errors, $httpCode = 500) { return Response::json(['errors' => $errors], $httpCode); diff --git a/framework/core/src/Api/Actions/TokenAction.php b/framework/core/src/Api/Actions/TokenAction.php index 8108c9d34..96ac6108f 100644 --- a/framework/core/src/Api/Actions/TokenAction.php +++ b/framework/core/src/Api/Actions/TokenAction.php @@ -29,7 +29,7 @@ class TokenAction extends BaseAction $user = $this->users->findByIdentification($identification); if (! $user || ! $user->checkPassword($password)) { - return $this->respondWithError('invalidLogin', 401); + return $this->respondWithError('invalidCredentials', 401); } $command = new GenerateAccessTokenCommand($user->id); diff --git a/framework/core/src/Api/ApiServiceProvider.php b/framework/core/src/Api/ApiServiceProvider.php index 0bbe49eca..a9c826211 100644 --- a/framework/core/src/Api/ApiServiceProvider.php +++ b/framework/core/src/Api/ApiServiceProvider.php @@ -12,6 +12,11 @@ class ApiServiceProvider extends ServiceProvider */ public function boot() { + $this->app->singleton( + 'Illuminate\Contracts\Debug\ExceptionHandler', + 'Flarum\Api\ExceptionHandler' + ); + include __DIR__.'/routes.php'; BaseSerializer::setActor($this->app['Flarum\Core\Support\Actor']); diff --git a/framework/core/src/Api/ExceptionHandler.php b/framework/core/src/Api/ExceptionHandler.php new file mode 100644 index 000000000..75003d3ad --- /dev/null +++ b/framework/core/src/Api/ExceptionHandler.php @@ -0,0 +1,75 @@ +is('api/*')) { + if ($e instanceof ValidationFailureException) { + return $this->renderValidationException($e); + } + if ($e instanceof PermissionDeniedException) { + return new Response(null, 401); + } + + $error = []; + if (Config::get('app.debug')) { + $error['code'] = (new \ReflectionClass($e))->getShortName(); + } + if ($detail = $e->getMessage()) { + $error['detail'] = $detail; + } + $statusCode = $e instanceof HttpException ? $e->getStatusCode() : 500; + if (count($error)) { + return $this->renderErrors([$error], $statusCode); + } else { + return new Response(null, $statusCode); + } + } + + return parent::render($request, $e); + } + + protected function renderErrors($errors, $httpCode = 500) + { + return new JsonResponse(['errors' => $errors], $httpCode); + } + + protected function renderValidationException(ValidationFailureException $e) + { + $errors = []; + foreach ($e->getErrors()->getMessages() as $field => $messages) { + $errors[] = [ + 'detail' => implode("\n", $messages), + 'path' => $field + ]; + } + return $this->renderErrors($errors, 422); + } +}