From e5f803d12222187b99a88a8cf2bb7ffdac6457fe Mon Sep 17 00:00:00 2001 From: Deon George Date: Mon, 22 Aug 2022 21:59:02 +1000 Subject: [PATCH] Add SlashCommand controller, and change routes to slack/* and api/slack/* --- src/Http/Controllers/SlackAppController.php | 9 +- .../Controllers/SlashCommandController.php | 98 +++++++++++++++++++ src/Http/Middleware/CheckRequest.php | 8 +- src/Models/Channel.php | 2 +- src/Models/User.php | 16 +++ src/routes.php | 5 + 6 files changed, 131 insertions(+), 7 deletions(-) create mode 100644 src/Http/Controllers/SlashCommandController.php diff --git a/src/Http/Controllers/SlackAppController.php b/src/Http/Controllers/SlackAppController.php index 6211cf6..bb1ea34 100644 --- a/src/Http/Controllers/SlackAppController.php +++ b/src/Http/Controllers/SlackAppController.php @@ -81,8 +81,13 @@ class SlackAppController extends Controller if (App::environment() == 'local') file_put_contents('/tmp/install',print_r($output,TRUE)); - if (! $output->ok) - abort(403,'Something didnt work, status not OK ['.(string)$response->getBody().']'); + if (! $output->ok) { + switch ($output->error) { + case 'invalid_code': abort(403,'Did you use the install button?'); + default: + abort(500,'Something didnt work, status not OK ['.(string)$response->getBody().']'); + } + } // Are we an enterprise? $eo = NULL; diff --git a/src/Http/Controllers/SlashCommandController.php b/src/Http/Controllers/SlashCommandController.php new file mode 100644 index 0000000..c392294 --- /dev/null +++ b/src/Http/Controllers/SlashCommandController.php @@ -0,0 +1,98 @@ +all(),TRUE)); + $o = new Message; + + // If the team is not active. + if (! $command->team()->active) { + Log::notice(sprintf('%s:IGNORING command, Team INACTIVE [%s]',static::LOGKEY,$command->team()->id)); + $o->text(sprintf("Sorry, it would appear you are not allowed to use me.\nYour instance hasnt been enabled.\nAsk an admin to install me [%s].",$command->team()->team_id)); + + return $o; + } + + if ($command->channel()) { + // If the channel is a direct message + if (str_starts_with($command->channel()->channel_id,'D')) { + Log::notice(sprintf('%s:IGNORING command, Channel is for direct messages [%s]',static::LOGKEY,$command->channel()->id)); + $o->text('Sorry, I dont work with direct messages yet. Please use me in a channel.'); + + return $o; + } + + // If the channel is not enabled + if (! $command->channel()->is_allowed) { + Log::notice(sprintf('%s:IGNORING command, Channel INACTIVE [%s]',static::LOGKEY,$request->channel_id)); + $o->text(sprintf('Sorry, it would appear this channel is not allowed to use me. %s may be able to help.',$command->team()->owner->slack_user)); + + return $o; + } + + // If the user hasnt been checked yet + if (is_null($command->user()->active)) { + Log::notice(sprintf('%s:IGNORING command, User UNKNOWN [%s]',static::LOGKEY,$command->user()->id)); + $o->text('Sorry, unfortunately I cannot work with you - as I dont know who you are (yet)...'); + + $a = new Attachment; + + if ($command->user()->created_at < Carbon::now()->subMinutes(5)) + $a->color('#CC0000') + ->text(sprintf('I probably should have figured out who you are by now, so something might be wrong. You might like to check with the %s.',$command->team()->owner->slack_user)); + else + $a->color('#008800') + ->text(sprintf('If I havent worked out who you are with the next 5 mins, you might like to check with the %s.',$command->team()->owner->slack_user)); + + $o->addAttachment($a); + + return $o; + } + + // If the user is not enabled + if (! $command->user()->isAllowed($command->channel())) { + Log::notice(sprintf('%s:IGNORING command, User INACTIVE [%s]',static::LOGKEY,$command->user()->id)); + $o->text(sprintf('Sorry, it would appear that you are not allowed to use me. %s may be able to help.',$command->team()->owner->slack_user)); + + return $o; + } + } + + // Check that we are active in the channel + if (! $command->channel() OR ! $command->channel()->active) { + $o->text('Hi, I am the *Ask the Experts* Bot'); + + $a = new Attachment; + $a->title('Greetings!') + ->text('Im not active in this channel, so I cant do anything here unless you invite me. Please invite me with `/invite`') + ->color('#FF8080'); + $o->addAttachment($a); + + return $o; + } + + if (! method_exists($command,'respond')) { + Log::alert(sprintf('%s:Cant respond to Command [%s], no respond method',static::LOGKEY,get_class($command)),['m'=>__METHOD__]); + abort(500,'No respond method() for '.get_class($command)); + } + + return ($x=$command->respond())->isEmpty() ? NULL : $x; + } +} \ No newline at end of file diff --git a/src/Http/Middleware/CheckRequest.php b/src/Http/Middleware/CheckRequest.php index fbcf310..3daab7d 100644 --- a/src/Http/Middleware/CheckRequest.php +++ b/src/Http/Middleware/CheckRequest.php @@ -32,10 +32,10 @@ class CheckRequest switch ($request->path()) { // For slashcmd full validation is done in the controller - case 'api/slashcmd': + case 'api/slack/slashcmd': return $next($request); - case 'api/event': + case 'api/slack/event': // URL Verification if ($request->input('type') === 'url_verification') { Log::debug(sprintf('%s:Responding directly to URL Verification',static::LOGKEY),['m'=>__METHOD__,'r'=>$request->all()]); @@ -45,11 +45,11 @@ class CheckRequest $event = EventFactory::make(new Payload($request->all(),TRUE)); break; - case 'api/imsgopt': + case 'api/slack/imsgopt': $event = OptionsFactory::make(new Payload(json_decode($request->payload,TRUE),TRUE)); break; - case 'api/imsg': + case 'api/slack/imsg': $event = InteractiveFactory::make(new Payload(json_decode($request->payload,TRUE),TRUE)); break; diff --git a/src/Models/Channel.php b/src/Models/Channel.php index 5dff683..2158234 100644 --- a/src/Models/Channel.php +++ b/src/Models/Channel.php @@ -30,7 +30,7 @@ class Channel extends Model */ public function getIsAllowedAttribute(): bool { - return $this->active; + return $this->active && $this->team->allow_guest; } /** diff --git a/src/Models/User.php b/src/Models/User.php index 720d87f..937d91d 100644 --- a/src/Models/User.php +++ b/src/Models/User.php @@ -2,6 +2,7 @@ namespace Slack\Models; +use App\Models\Slack\Channel; use App\Models\Slack\Enterprise as AppEnterprise; use App\Models\Slack\Team as AppTeam; @@ -63,4 +64,19 @@ class User extends Model return $this->team_id ? $this->team : (($x=$this->enterprise->teams) ? $x->first() : NULL); } + + /* METHODS */ + + /** + * Return if the user is allowed to use this bot + * If the user is active status is NULL, but the channel or team allow guests, then the user is allowed. + * If the user is active status is FALSE, then the user is not allowed. + * + * @param Channel $co + * @return bool + */ + public function isAllowed(Channel $co): bool + { + return $this->active || (($this->active !== FALSE) && $co->allow_guest); + } } \ No newline at end of file diff --git a/src/routes.php b/src/routes.php index 4180e7d..8e0ee31 100644 --- a/src/routes.php +++ b/src/routes.php @@ -38,4 +38,9 @@ app('router') 'uses' => 'InteractiveOptionsController@fire', 'as' => 'imsgopt', ]); + + $router->post('slack/slashcmd', [ + 'uses' => 'SlashCommandController@fire', + 'as' => 'slashcommand', + ]); });