Skip to content

Commit 0be5cf7

Browse files
committed
use access tokens per workspace
1 parent ad75e6f commit 0be5cf7

28 files changed

+2607
-245
lines changed

app-modules/slack-events-bot/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"version": "1.0",
77
"autoload": {
88
"psr-4": {
9-
"HackGreenville\\SlackEventsBot\\": "src/"
9+
"HackGreenville\\SlackEventsBot\\": "src/",
10+
"HackGreenville\\SlackEventsBot\\Database\\Factories\\": "./database/factories/"
1011
}
1112
},
1213
"autoload-dev": {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace HackGreenville\SlackEventsBot\Database\Factories;
4+
5+
use HackGreenville\SlackEventsBot\Models\SlackChannel;
6+
use HackGreenville\SlackEventsBot\Models\SlackWorkspace;
7+
use Illuminate\Database\Eloquent\Factories\Factory;
8+
9+
class SlackChannelFactory extends Factory
10+
{
11+
protected $model = SlackChannel::class;
12+
13+
public function definition(): array
14+
{
15+
return [
16+
'slack_channel_id' => $this->faker->unique()->regexify('[C][A-Z0-9]{10}'),
17+
'slack_workspace_id' => SlackWorkspace::factory(),
18+
];
19+
}
20+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace HackGreenville\SlackEventsBot\Database\Factories;
4+
5+
use HackGreenville\SlackEventsBot\Models\SlackChannel;
6+
use HackGreenville\SlackEventsBot\Models\SlackMessage;
7+
use Illuminate\Database\Eloquent\Factories\Factory;
8+
use Illuminate\Support\Carbon;
9+
10+
class SlackMessageFactory extends Factory
11+
{
12+
protected $model = SlackMessage::class;
13+
14+
public function definition(): array
15+
{
16+
return [
17+
'week' => Carbon::now()->startOfWeek(),
18+
'message' => $this->faker->sentence,
19+
'message_timestamp' => now()->timestamp . '.' . $this->faker->randomNumber(6, true),
20+
'sequence_position' => $this->faker->numberBetween(0, 10),
21+
'channel_id' => SlackChannel::factory(),
22+
];
23+
}
24+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace HackGreenville\SlackEventsBot\Database\Factories;
4+
5+
use HackGreenville\SlackEventsBot\Models\SlackWorkspace;
6+
use Illuminate\Database\Eloquent\Factories\Factory;
7+
8+
class SlackWorkspaceFactory extends Factory
9+
{
10+
/**
11+
* The name of the factory's corresponding model.
12+
*
13+
* @var string
14+
*/
15+
protected $model = SlackWorkspace::class;
16+
17+
/**
18+
* Define the model's default state.
19+
*
20+
* @return array
21+
*/
22+
public function definition(): array
23+
{
24+
return [
25+
'team_id' => $this->faker->unique()->regexify('[T][A-Z0-9]{10}'),
26+
'team_name' => $this->faker->company,
27+
'access_token' => $this->faker->sha256,
28+
'bot_user_id' => $this->faker->unique()->regexify('[U][A-Z0-9]{10}'),
29+
];
30+
}
31+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration {
8+
/**
9+
* Run the migrations.
10+
*/
11+
public function up(): void
12+
{
13+
Schema::table('slack_channels', function (Blueprint $table) {
14+
$table->string('slack_workspace_id')->nullable()->after('channel_id');
15+
});
16+
}
17+
18+
/**
19+
* Reverse the migrations.
20+
*/
21+
public function down(): void
22+
{
23+
Schema::table('slack_channels', function (Blueprint $table) {
24+
$table->dropColumn('slack_workspace_id');
25+
});
26+
}
27+
};
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration {
8+
/**
9+
* Run the migrations.
10+
*/
11+
public function up(): void
12+
{
13+
Schema::table('slack_workspaces', function (Blueprint $table) {
14+
$table->string('domain')->nullable();
15+
});
16+
}
17+
18+
/**
19+
* Reverse the migrations.
20+
*/
21+
public function down(): void
22+
{
23+
Schema::table('slack_workspaces', function (Blueprint $table) {
24+
$table->dropColumn('domain');
25+
});
26+
}
27+
};

app-modules/slack-events-bot/routes/web.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,5 @@
33
use HackGreenville\SlackEventsBot\Http\Controllers\SlackController;
44
use Illuminate\Support\Facades\Route;
55

6-
Route::prefix('slack')->group(function () {
7-
Route::get('/install', [SlackController::class, 'install'])->name('slack.install');
8-
Route::get('/auth', [SlackController::class, 'auth'])->name('slack.auth');
9-
});
6+
Route::get('/install', [SlackController::class, 'install'])->name('install');
7+
Route::get('/auth', [SlackController::class, 'auth'])->name('auth');

app-modules/slack-events-bot/src/Http/Controllers/SlackController.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,26 +122,27 @@ private function handleSlashCommand(array $payload): Response
122122
$command = $payload['command'];
123123
$userId = $payload['user_id'];
124124
$channelId = $payload['channel_id'];
125+
$teamId = $payload['team_id'];
125126
$teamDomain = $payload['team_domain'] ?? null;
126127

127128
$originalCommand = $command;
128129

129130
// Normalize dev commands to match production commands
130-
if (app()->isLocal() && str_starts_with($command, '/dev_')) {
131+
if (true || app()->isLocal() && str_starts_with($command, '/dev_')) {
131132
$command = str_replace('/dev_', '/', $command);
132133
Log::info('Normalized dev command', ['original' => $originalCommand, 'normalized' => $command]);
133134
}
134135

135136
switch ($command) {
136137
case '/add_channel':
137138
Log::info('Executing /add_channel command', ['user_id' => $userId, 'channel_id' => $channelId]);
138-
if ( ! $this->authService->isAdmin($userId)) {
139+
if ( ! $this->authService->isAdmin($userId, $teamId)) {
139140
Log::warning('/add_channel failed: user is not an admin', ['user_id' => $userId]);
140141
return response('You must be a workspace admin in order to run `/add_channel`');
141142
}
142143

143144
try {
144-
$this->databaseService->addChannel($channelId);
145+
$this->databaseService->addChannel($channelId, $teamId);
145146
Log::info('Successfully added channel', ['channel_id' => $channelId]);
146147
return response('Added channel to slack events bot 👍');
147148
} catch (Exception $e) {
@@ -154,7 +155,7 @@ private function handleSlashCommand(array $payload): Response
154155

155156
case '/remove_channel':
156157
Log::info('Executing /remove_channel command', ['user_id' => $userId, 'channel_id' => $channelId]);
157-
if ( ! $this->authService->isAdmin($userId)) {
158+
if ( ! $this->authService->isAdmin($userId, $teamId)) {
158159
Log::warning('/remove_channel failed: user is not an admin', ['user_id' => $userId]);
159160
return response('You must be a workspace admin in order to run `/remove_channel`');
160161
}
@@ -174,7 +175,7 @@ private function handleSlashCommand(array $payload): Response
174175
case '/check_api':
175176
Log::info('Executing /check_api command', ['user_id' => $userId, 'team_domain' => $teamDomain]);
176177
// Check cooldown
177-
if ( ! app()->isLocal() && $teamDomain) {
178+
if (false && ! app()->isLocal() && $teamDomain) {
178179
$expiryTime = $this->databaseService->getCooldownExpiryTime($teamDomain, 'check_api');
179180

180181
if ($expiryTime && $expiryTime->isFuture()) {

app-modules/slack-events-bot/src/Models/SlackChannel.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,33 @@
22

33
namespace HackGreenville\SlackEventsBot\Models;
44

5+
use HackGreenville\SlackEventsBot\Database\Factories\SlackChannelFactory;
6+
use Illuminate\Database\Eloquent\Factories\HasFactory;
57
use Illuminate\Database\Eloquent\Model;
8+
use Illuminate\Database\Eloquent\Relations\BelongsTo;
69
use Illuminate\Database\Eloquent\Relations\HasMany;
710

811
class SlackChannel extends Model
912
{
13+
use HasFactory;
14+
1015
protected $fillable = [
1116
'slack_channel_id',
17+
'slack_workspace_id',
1218
];
1319

1420
public function messages(): HasMany
1521
{
1622
return $this->hasMany(SlackMessage::class, 'channel_id');
1723
}
24+
25+
public function workspace(): BelongsTo
26+
{
27+
return $this->belongsTo(SlackWorkspace::class, 'slack_workspace_id');
28+
}
29+
30+
protected static function newFactory()
31+
{
32+
return SlackChannelFactory::new();
33+
}
1834
}

app-modules/slack-events-bot/src/Models/SlackMessage.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@
22

33
namespace HackGreenville\SlackEventsBot\Models;
44

5+
use HackGreenville\SlackEventsBot\Database\Factories\SlackMessageFactory;
6+
use Illuminate\Database\Eloquent\Factories\HasFactory;
57
use Illuminate\Database\Eloquent\Model;
68
use Illuminate\Database\Eloquent\Relations\BelongsTo;
79

810
class SlackMessage extends Model
911
{
12+
use HasFactory;
13+
1014
protected $fillable = [
1115
'week',
1216
'message_timestamp',
@@ -23,4 +27,9 @@ public function channel(): BelongsTo
2327
{
2428
return $this->belongsTo(SlackChannel::class, 'channel_id');
2529
}
30+
31+
protected static function newFactory()
32+
{
33+
return SlackMessageFactory::new();
34+
}
2635
}

0 commit comments

Comments
 (0)