diff --git a/.env.testing b/.env.testing
index d0361048..2191bfc0 100644
--- a/.env.testing
+++ b/.env.testing
@@ -1,6 +1,6 @@
APP_NAME=Laravel
APP_ENV=local
-APP_KEY=base64:47yorkyoH3qCrKKO4eG6LpZUogoTC51qey5vYq/O3AM=
+APP_KEY=base64:XP4FSfZLrj3n2MbhbOVWp4ldCbU0Ew+bhiEpHyOpxVw=
APP_DEBUG=true
APP_URL=http://localhost
APP_DEMO=false
diff --git a/config/content.php b/config/content.php
index 97f0e2ad..ed54275b 100644
--- a/config/content.php
+++ b/config/content.php
@@ -95,6 +95,10 @@ return [
'name' => 'allowed_adsense',
'value' => 0,
],
+ [
+ 'name' => 'allowed_recaptcha',
+ 'value' => 0,
+ ],
],
'extended' => [
[
@@ -177,6 +181,10 @@ return [
'name' => 'allowed_adsense',
'value' => 0,
],
+ [
+ 'name' => 'allowed_recaptcha',
+ 'value' => 0,
+ ],
// Subscription
[
diff --git a/database/migrations/2021_08_24_080638_create_team_folder_invitations_table.php b/database/migrations/2021_08_24_080638_create_team_folder_invitations_table.php
index fc540d11..27e8e06a 100644
--- a/database/migrations/2021_08_24_080638_create_team_folder_invitations_table.php
+++ b/database/migrations/2021_08_24_080638_create_team_folder_invitations_table.php
@@ -20,7 +20,7 @@ class CreateTeamFolderInvitationsTable extends Migration
$table->text('email');
$table->string('color')->nullable();
$table->enum('permission', ['can-edit', 'can-view', 'can-view-and-download']);
- $table->enum('status', ['pending', 'accepted', 'rejected'])->default('pending');
+ $table->enum('status', ['pending', 'accepted', 'waiting-for-registration', 'rejected'])->default('pending');
$table->timestamps();
$table->charset = 'utf8mb4';
$table->collation = 'utf8mb4_unicode_ci';
diff --git a/resources/js/views/Teams/Invitation.vue b/resources/js/views/Teams/Invitation.vue
index 8237e41a..87cc28e8 100644
--- a/resources/js/views/Teams/Invitation.vue
+++ b/resources/js/views/Teams/Invitation.vue
@@ -6,22 +6,37 @@
v-if="invitation"
:title="$t('Invitation To Join Team Folder')"
:description="
- $t('{name} invite you to join with his team into shared team folder', {
+ $t('Jane invite you to join with his team into shared team folder', {
name: invitation.data.relationships.inviter.data.attributes.name,
})
"
>
-
+
+
+
@@ -37,10 +52,17 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -106,6 +146,11 @@ export default {
},
computed: {
...mapGetters(['config']),
+ acceptButton() {
+ return this.invitation && this.invitation.data.attributes.isExistedUser
+ ? this.$t('Accept Invitation')
+ : this.$t('Accept and Register Account')
+ },
},
data() {
return {
@@ -121,7 +166,12 @@ export default {
axios
.put(`/api/teams/invitations/${this.$router.currentRoute.params.id}`)
.then(() => {
- this.goToAuthPage('accepted')
+
+ if (this.invitation.data.attributes.isExistedUser) {
+ this.goToAuthPage('accepted')
+ } else {
+ this.$router.push({name: 'SignUp'})
+ }
})
.catch(() => {
this.$isSomethingWrong()
diff --git a/src/App/Console/Commands/SetupDevEnvironment.php b/src/App/Console/Commands/SetupDevEnvironment.php
index 941a5b47..dd5abab5 100644
--- a/src/App/Console/Commands/SetupDevEnvironment.php
+++ b/src/App/Console/Commands/SetupDevEnvironment.php
@@ -1090,6 +1090,10 @@ class SetupDevEnvironment extends Command
'name' => 'subscription_type',
'value' => 'fixed',
],
+ [
+ 'name' => 'allowed_recaptcha',
+ 'value' => 0,
+ ],
])->each(function ($col) {
Setting::updateOrCreate([
'name' => $col['name'],
diff --git a/src/App/Console/Commands/SetupProdEnvironment.php b/src/App/Console/Commands/SetupProdEnvironment.php
index 96e4822c..78407829 100644
--- a/src/App/Console/Commands/SetupProdEnvironment.php
+++ b/src/App/Console/Commands/SetupProdEnvironment.php
@@ -187,6 +187,10 @@ class SetupProdEnvironment extends Command
'name' => 'billing_vat_number',
'value' => null,
],
+ [
+ 'name' => 'allowed_recaptcha',
+ 'value' => 0,
+ ],
])->each(function ($col) {
Setting::forceCreate([
'name' => $col['name'],
diff --git a/src/App/Users/Actions/CreateNewUserAction.php b/src/App/Users/Actions/CreateNewUserAction.php
index d52ecfae..7d7162fe 100644
--- a/src/App/Users/Actions/CreateNewUserAction.php
+++ b/src/App/Users/Actions/CreateNewUserAction.php
@@ -1,17 +1,19 @@
$data->avatar,
]);
+ // Join to previously accepted team folder invitations
+ TeamFolderInvitation::where('email', $user->email)
+ ->where('status', 'waiting-for-registration')
+ ->cursor()
+ ->each(function ($invitation) use ($user) {
+ TeamFolderMember::create([
+ 'user_id' => $user->id,
+ 'parent_id' => $invitation->parent_id,
+ 'permission' => $invitation->permission,
+ ]);
+
+ $invitation->accept();
+ });
+
// Subscribe user for metered billing
if ($settings['subscription_type'] === 'metered') {
($this->autoSubscribeForMeteredBilling)($user);
}
// Mark as verified if verification is disabled
- if (! $data->password || ! intval($settings['user_verification'])) {
+ if (!$data->password || !intval($settings['user_verification'])) {
$user->markEmailAsVerified();
}
diff --git a/src/App/Users/Requests/RegisterUserRequest.php b/src/App/Users/Requests/RegisterUserRequest.php
index f4ff59d3..8b13f59b 100644
--- a/src/App/Users/Requests/RegisterUserRequest.php
+++ b/src/App/Users/Requests/RegisterUserRequest.php
@@ -32,7 +32,7 @@ class RegisterUserRequest extends FormRequest
'email' => ['required', 'string', 'email', 'max:255', 'unique:users,email', new EmailProvider],
'name' => 'required|string|max:255',
'password' => $this->passwordRules(),
- 'reCaptcha' => [new RequiredIf(get_settings('allowed_recaptcha') == 1), 'string', app(ReCaptchaRules::class)],
+ 'reCaptcha' => [new RequiredIf(get_settings('allowed_recaptcha') == 1), 'string', 'nullable', app(ReCaptchaRules::class)],
];
}
}
diff --git a/src/Domain/SetupWizard/Controllers/StoreEnvironmentSettingsController.php b/src/Domain/SetupWizard/Controllers/StoreEnvironmentSettingsController.php
index 22e97982..88bebb5d 100644
--- a/src/Domain/SetupWizard/Controllers/StoreEnvironmentSettingsController.php
+++ b/src/Domain/SetupWizard/Controllers/StoreEnvironmentSettingsController.php
@@ -81,8 +81,9 @@ class StoreEnvironmentSettingsController extends Controller
'APP_DEBUG' => 'false',
],
'local' => [
- 'APP_ENV' => 'local',
- 'APP_DEBUG' => 'true',
+ 'APP_ENV' => 'local',
+ 'APP_DEBUG' => 'true',
+ 'QUEUE_CONNECTION' => 'sync',
],
];
diff --git a/src/Domain/Teams/Controllers/InvitationsController.php b/src/Domain/Teams/Controllers/InvitationsController.php
index e0b106fc..1192dfff 100644
--- a/src/Domain/Teams/Controllers/InvitationsController.php
+++ b/src/Domain/Teams/Controllers/InvitationsController.php
@@ -2,6 +2,7 @@
namespace Domain\Teams\Controllers;
use App\Users\Models\User;
+use Domain\Teams\Models\TeamFolderMember;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
@@ -13,7 +14,7 @@ class InvitationsController extends Controller
{
public function show(TeamFolderInvitation $invitation)
{
- if ($invitation->status === 'accepted') {
+ if ($invitation->status !== 'pending') {
abort(410);
}
@@ -23,19 +24,24 @@ class InvitationsController extends Controller
public function update(
TeamFolderInvitation $invitation
): ResponseFactory | Response {
- $user = User::where('email', $invitation->email)
- ->firstOrFail();
+ $user = User::where('email', $invitation->email);
- $invitation->update([
- 'status' => 'accepted',
- ]);
+ if ($user->exists()) {
+ $invitation->accept();
- DB::table('team_folder_members')
- ->insert([
+ // Store team member
+ TeamFolderMember::create([
+ 'user_id' => $user->first()->id,
'parent_id' => $invitation->parent_id,
- 'user_id' => $user->id,
- 'permission' => 'can-edit',
+ 'permission' => $invitation->permission,
]);
+ }
+
+ if ($user->doesntExist()) {
+ $invitation->update([
+ 'status' => 'waiting-for-registration',
+ ]);
+ }
return response('Done', 204);
}
@@ -43,9 +49,7 @@ class InvitationsController extends Controller
public function destroy(
TeamFolderInvitation $invitation
): ResponseFactory | Response {
- $invitation->update([
- 'status' => 'rejected',
- ]);
+ $invitation->reject();
return response('Done', 204);
}
diff --git a/src/Domain/Teams/Models/TeamFolderInvitation.php b/src/Domain/Teams/Models/TeamFolderInvitation.php
index 4a2cca69..9537893b 100644
--- a/src/Domain/Teams/Models/TeamFolderInvitation.php
+++ b/src/Domain/Teams/Models/TeamFolderInvitation.php
@@ -31,6 +31,18 @@ class TeamFolderInvitation extends Model
protected $keyType = 'string';
+ public function accept() {
+ $this->update([
+ 'status' => 'accepted',
+ ]);
+ }
+
+ public function reject() {
+ $this->update([
+ 'status' => 'rejected',
+ ]);
+ }
+
protected static function newFactory(): TeamFolderInvitationFactory
{
return TeamFolderInvitationFactory::new();
diff --git a/src/Domain/Teams/Resources/TeamInvitationResource.php b/src/Domain/Teams/Resources/TeamInvitationResource.php
index b09f5c07..df8d0504 100644
--- a/src/Domain/Teams/Resources/TeamInvitationResource.php
+++ b/src/Domain/Teams/Resources/TeamInvitationResource.php
@@ -1,6 +1,7 @@
$this->color,
'status' => $this->status,
'permission' => $this->permission,
+ 'isExistedUser' => User::where('email', $this->email)->exists(),
],
'relationships' => [
$this->mergeWhen($this->inviter, fn () => [
diff --git a/tests/Domain/Homepage/HomepageTest.php b/tests/Domain/Homepage/HomepageTest.php
index 2aff3976..0eac15e9 100644
--- a/tests/Domain/Homepage/HomepageTest.php
+++ b/tests/Domain/Homepage/HomepageTest.php
@@ -41,7 +41,7 @@ class HomepageTest extends TestCase
{
$this->get('/')
->assertStatus(200)
- ->assertSee('setup-disclaimer')
+ ->assertSee('installation-needed')
->assertSee('VueFileManager');
}
diff --git a/tests/Domain/Settings/SettingsTest.php b/tests/Domain/Settings/SettingsTest.php
index 0387f5cf..4b50d2cf 100644
--- a/tests/Domain/Settings/SettingsTest.php
+++ b/tests/Domain/Settings/SettingsTest.php
@@ -190,12 +190,12 @@ class SettingsTest extends TestCase
$this
->actingAs($admin)
->postJson('/api/admin/settings/email', [
- 'driver' => 'smtp',
- 'host' => 'smtp.email.com',
- 'port' => 25,
- 'username' => 'john@doe.com',
- 'password' => 'secret',
- 'encryption' => 'tls',
+ 'mailDriver' => 'smtp',
+ 'smtp.host' => 'smtp.email.com',
+ 'smtp.port' => 25,
+ 'smtp.username' => 'john@doe.com',
+ 'smtp.password' => 'secret',
+ 'smtp.encryption' => 'tls',
])->assertStatus(204);
}
}
diff --git a/tests/Domain/SetupWizard/SetupWizardTest.php b/tests/Domain/SetupWizard/SetupWizardTest.php
index dd3100d9..15f66de7 100644
--- a/tests/Domain/SetupWizard/SetupWizardTest.php
+++ b/tests/Domain/SetupWizard/SetupWizardTest.php
@@ -21,7 +21,7 @@ class SetupWizardTest extends TestCase
$this->postJson('/api/setup/purchase-code', [
'purchaseCode' => '8624194e-3156-4cd0-944e-3440fcecdacb',
- ])->assertStatus(204);
+ ])->assertStatus(201);
}
/**
diff --git a/tests/Domain/Sharing/VisitorBrowseTest.php b/tests/Domain/Sharing/VisitorBrowseTest.php
index 710f56c9..cb2c5ff3 100644
--- a/tests/Domain/Sharing/VisitorBrowseTest.php
+++ b/tests/Domain/Sharing/VisitorBrowseTest.php
@@ -1,4 +1,5 @@
getJson("/api/browse/folders/$root->id/$share->token")
->assertStatus(200)
->assertJsonFragment([
@@ -260,10 +261,11 @@ class VisitorBrowseTest extends TestCase
$tree = [
[
- 'id' => $share->item_id,
- 'name' => 'Home',
- 'location' => 'public',
- 'folders' => [
+ 'name' => 'Home',
+ 'location' => 'public',
+ 'isMovable' => true,
+ 'isOpen' => true,
+ 'folders' => [
[
'id' => $folder_level_2->id,
'parent_id' => $folder_level_1->id,
@@ -308,7 +310,7 @@ class VisitorBrowseTest extends TestCase
}
// Check public shared item
- if (! $is_protected) {
+ if (!$is_protected) {
$this->getJson("/api/browse/navigation/$share->token")
->assertStatus(200)
->assertExactJson($tree);
@@ -360,7 +362,7 @@ class VisitorBrowseTest extends TestCase
}
// Check public shared item
- if (! $is_protected) {
+ if (!$is_protected) {
$this->getJson("/api/browse/search/$share->token?query=doc")
->assertStatus(200)
->assertJsonFragment([
@@ -411,7 +413,7 @@ class VisitorBrowseTest extends TestCase
}
// Check public shared item
- if (! $is_protected) {
+ if (!$is_protected) {
$this->getJson("/api/browse/search/$share->token?query=doc")
->assertStatus(200)
->assertJsonFragment([]);
@@ -458,7 +460,7 @@ class VisitorBrowseTest extends TestCase
}
// Check public shared item
- if (! $is_protected) {
+ if (!$is_protected) {
$this->getJson("/api/browse/file/$share->token")
->assertStatus(200)
->assertJsonFragment([
diff --git a/tests/Domain/Sharing/VisitorManipulatingTest.php b/tests/Domain/Sharing/VisitorManipulatingTest.php
index c741d3e9..0cf3c903 100644
--- a/tests/Domain/Sharing/VisitorManipulatingTest.php
+++ b/tests/Domain/Sharing/VisitorManipulatingTest.php
@@ -300,6 +300,7 @@ class VisitorManipulatingTest extends TestCase
collect([true, false])
->each(function ($is_protected) {
$user = User::factory()
+ ->hasSettings()
->create();
$folder = Folder::factory(Folder::class)
diff --git a/tests/Domain/Teams/TeamManagementTest.php b/tests/Domain/Teams/TeamManagementTest.php
index 79c07bed..b13f7c73 100644
--- a/tests/Domain/Teams/TeamManagementTest.php
+++ b/tests/Domain/Teams/TeamManagementTest.php
@@ -44,7 +44,7 @@ class TeamManagementTest extends TestCase
/**
* @test
*/
- public function it_accept_team_folder_invite()
+ public function it_accept_team_folder_invite_as_registered_user()
{
$member = User::factory()
->create([
@@ -59,7 +59,7 @@ class TeamManagementTest extends TestCase
'parent_id' => $folder->id,
'email' => $member->email,
'status' => 'pending',
- 'permission' => 'can-edit',
+ 'permission' => 'can-view',
]);
$this
@@ -75,8 +75,69 @@ class TeamManagementTest extends TestCase
->assertDatabaseHas('team_folder_members', [
'parent_id' => $folder->id,
'user_id' => $member->id,
+ 'permission' => 'can-view',
+ ]);
+ }
+
+ /**
+ * @test
+ */
+ public function it_accept_team_folder_invite_as_guest_user()
+ {
+ $folder = Folder::factory()
+ ->create();
+
+ $invitation = TeamFolderInvitation::factory()
+ ->create([
+ 'parent_id' => $folder->id,
+ 'email' => 'howdy@hi5ve.digital',
+ 'status' => 'pending',
'permission' => 'can-edit',
]);
+
+ $this
+ ->putJson("/api/teams/invitations/{$invitation->id}")
+ ->assertNoContent();
+
+ $this
+ ->assertDatabaseHas('team_folder_invitations', [
+ 'parent_id' => $folder->id,
+ 'status' => 'waiting-for-registration',
+ ])
+ ->assertDatabaseMissing('team_folder_members', [
+ 'parent_id' => $folder->id,
+ 'permission' => 'can-edit',
+ ]);
+ }
+
+ /**
+ * @test
+ */
+ public function it_apply_accepted_invitation_after_user_registration()
+ {
+ $invitation = TeamFolderInvitation::factory()
+ ->create([
+ 'email' => 'john@doe.com',
+ 'status' => 'waiting-for-registration',
+ ]);
+
+ $this->postJson('api/register', [
+ 'email' => 'john@doe.com',
+ 'password' => 'SecretPassword',
+ 'password_confirmation' => 'SecretPassword',
+ 'name' => 'John Doe',
+ ])->assertStatus(201);
+
+ $this
+ ->assertDatabaseHas('team_folder_invitations', [
+ 'parent_id' => $invitation->parent_id,
+ 'status' => 'accepted',
+ ])
+ ->assertDatabaseHas('team_folder_members', [
+ 'parent_id' => $invitation->parent_id,
+ 'user_id' => User::first()->id,
+ 'permission' => $invitation->permission,
+ ]);
}
/**