mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-10 09:12:15 +01:00
Added timezone to registration
This commit is contained in:
@@ -6,6 +6,7 @@ namespace App\Actions\Fortify;
|
||||
|
||||
use App\Models\Organization;
|
||||
use App\Models\User;
|
||||
use App\Service\TimezoneService;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
@@ -48,11 +49,17 @@ class CreateNewUser implements CreatesNewUsers
|
||||
'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['accepted', 'required'] : '',
|
||||
])->validate();
|
||||
|
||||
return DB::transaction(function () use ($input) {
|
||||
$timezone = 'UTC';
|
||||
if (array_key_exists('timezone', $input) && is_string($input['timezone']) && app(TimezoneService::class)->isValid($input['timezone'])) {
|
||||
$timezone = $input['timezone'];
|
||||
}
|
||||
|
||||
return DB::transaction(function () use ($input, $timezone) {
|
||||
return tap(User::create([
|
||||
'name' => $input['name'],
|
||||
'email' => $input['email'],
|
||||
'password' => Hash::make($input['password']),
|
||||
'timezone' => $timezone,
|
||||
]), function (User $user) {
|
||||
$this->createTeam($user);
|
||||
});
|
||||
|
||||
@@ -53,6 +53,7 @@ class ClockifyTimeEntriesImporter extends DefaultImporter
|
||||
'email' => $record['Email'],
|
||||
], [
|
||||
'name' => $record['User'],
|
||||
'timezone' => 'UTC',
|
||||
'is_placeholder' => true,
|
||||
]);
|
||||
$clientId = null;
|
||||
|
||||
@@ -12,6 +12,7 @@ use App\Models\Task;
|
||||
use App\Models\User;
|
||||
use App\Service\ColorService;
|
||||
use App\Service\Import\ImportDatabaseHelper;
|
||||
use App\Service\TimezoneService;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
abstract class DefaultImporter implements ImporterContract
|
||||
@@ -47,6 +48,8 @@ abstract class DefaultImporter implements ImporterContract
|
||||
|
||||
protected ColorService $colorService;
|
||||
|
||||
protected TimezoneService $timezoneService;
|
||||
|
||||
public function init(Organization $organization): void
|
||||
{
|
||||
$this->organization = $organization;
|
||||
@@ -62,6 +65,10 @@ abstract class DefaultImporter implements ImporterContract
|
||||
'required',
|
||||
'max:255',
|
||||
],
|
||||
'timezone' => [
|
||||
'required',
|
||||
'timezone:all',
|
||||
],
|
||||
]);
|
||||
$this->projectImportHelper = new ImportDatabaseHelper(Project::class, ['name', 'organization_id'], true, function (Builder $builder) {
|
||||
return $builder->where('organization_id', $this->organization->id);
|
||||
@@ -97,6 +104,7 @@ abstract class DefaultImporter implements ImporterContract
|
||||
]);
|
||||
$this->timeEntriesCreated = 0;
|
||||
$this->colorService = app(ColorService::class);
|
||||
$this->timezoneService = app(TimezoneService::class);
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
|
||||
@@ -83,6 +83,7 @@ class TogglDataImporter extends DefaultImporter
|
||||
'email' => $workspaceUser->email,
|
||||
], [
|
||||
'name' => $workspaceUser->name,
|
||||
'timezone' => $workspaceUser->timezone ?? 'UTC',
|
||||
'is_placeholder' => true,
|
||||
], (string) $workspaceUser->id);
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ class TogglTimeEntriesImporter extends DefaultImporter
|
||||
'email' => $record['Email'],
|
||||
], [
|
||||
'name' => $record['User'],
|
||||
'timezone' => 'UTC',
|
||||
'is_placeholder' => true,
|
||||
]);
|
||||
$clientId = null;
|
||||
|
||||
@@ -32,4 +32,9 @@ class TimezoneService
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
public function isValid(string $timezone): bool
|
||||
{
|
||||
return in_array($timezone, $this->getTimezones(), true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ return new class extends Migration
|
||||
$table->boolean('is_placeholder')->default(false);
|
||||
$table->foreignUuid('current_team_id')->nullable();
|
||||
$table->string('profile_photo_path', 2048)->nullable();
|
||||
$table->string('timezone')->nullable();
|
||||
$table->string('timezone');
|
||||
$table->timestamps();
|
||||
|
||||
$table->uniqueIndex('email')
|
||||
|
||||
@@ -18,7 +18,7 @@ export default defineConfig({
|
||||
/* Retry on CI only */
|
||||
retries: process.env.CI ? 1 : 0,
|
||||
/* Opt out of parallel tests on CI. */
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
workers: process.env.CI ? 1 : 1,
|
||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||
reporter: process.env.CI ? 'line' : 'html',
|
||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||
|
||||
@@ -15,6 +15,7 @@ const form = useForm({
|
||||
password: '',
|
||||
password_confirmation: '',
|
||||
terms: false,
|
||||
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone ?? null,
|
||||
});
|
||||
|
||||
const submit = () => {
|
||||
|
||||
@@ -203,8 +203,17 @@ const page = usePage<{
|
||||
<!-- Timezone -->
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<InputLabel for="timezone" value="Timezone" />
|
||||
<select name="timezone" id="timezone" v-model="form.timezone" class="mt-1 block w-full border-input-border bg-input-background text-white focus:border-input-border-active rounded-md shadow-sm">
|
||||
<option v-for="timezone in $page.props.timezones" :value="timezone">
|
||||
<select
|
||||
name="timezone"
|
||||
id="timezone"
|
||||
v-model="form.timezone"
|
||||
required
|
||||
class="mt-1 block w-full border-input-border bg-input-background text-white focus:border-input-border-active rounded-md shadow-sm">
|
||||
<option value="" disabled>Select a Timezone</option>
|
||||
<option
|
||||
v-for="timezone in $page.props.timezones"
|
||||
:key="timezone"
|
||||
:value="timezone">
|
||||
{{ timezone }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
@@ -49,6 +49,42 @@ class RegistrationTest extends TestCase
|
||||
|
||||
$this->assertAuthenticated();
|
||||
$response->assertRedirect(RouteServiceProvider::HOME);
|
||||
$user = User::where('email', 'test@example.com')->firstOrFail();
|
||||
$this->assertSame('UTC', $user->timezone);
|
||||
}
|
||||
|
||||
public function test_new_users_can_register_and_frontend_can_send_timezone_for_user(): void
|
||||
{
|
||||
$response = $this->post('/register', [
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@example.com',
|
||||
'password' => 'password',
|
||||
'password_confirmation' => 'password',
|
||||
'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature(),
|
||||
'timezone' => 'Europe/Berlin',
|
||||
]);
|
||||
|
||||
$this->assertAuthenticated();
|
||||
$response->assertRedirect(RouteServiceProvider::HOME);
|
||||
$user = User::where('email', 'test@example.com')->firstOrFail();
|
||||
$this->assertSame('Europe/Berlin', $user->timezone);
|
||||
}
|
||||
|
||||
public function test_new_users_can_register_and_ignores_invalid_timezones_from_frontend(): void
|
||||
{
|
||||
$response = $this->post('/register', [
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@example.com',
|
||||
'password' => 'password',
|
||||
'password_confirmation' => 'password',
|
||||
'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature(),
|
||||
'timezone' => 'Unknown timezone',
|
||||
]);
|
||||
|
||||
$this->assertAuthenticated();
|
||||
$response->assertRedirect(RouteServiceProvider::HOME);
|
||||
$user = User::where('email', 'test@example.com')->firstOrFail();
|
||||
$this->assertSame('UTC', $user->timezone);
|
||||
}
|
||||
|
||||
public function test_new_users_can_not_register_if_user_with_email_already_exists(): void
|
||||
|
||||
@@ -42,6 +42,7 @@ class ImportDatabaseHelperTest extends TestCase
|
||||
'email' => 'test@mail.test',
|
||||
], [
|
||||
'name' => 'Test',
|
||||
'timezone' => 'UTC',
|
||||
]);
|
||||
|
||||
// Assert
|
||||
|
||||
Reference in New Issue
Block a user