Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117390738
D1213.1774824461.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
65 KB
Referenced Files
None
Subscribers
None
D1213.1774824461.diff
View Options
diff --git a/src/app/Backends/LDAP.php b/src/app/Backends/LDAP.php
--- a/src/app/Backends/LDAP.php
+++ b/src/app/Backends/LDAP.php
@@ -7,6 +7,13 @@
class LDAP
{
+ /** @const array UserSettings used by th backend */
+ public const USER_SETTINGS = [
+ 'first_name',
+ 'last_name',
+ 'organization',
+ ];
+
/**
* Create a domain in LDAP.
*
@@ -368,11 +375,9 @@
$entry['givenname'] = $firstName;
$entry['sn'] = $lastName;
$entry['userpassword'] = $user->password_ldap;
-
$entry['inetuserstatus'] = $user->status;
-
+ $entry['o'] = $user->getSetting('organization');
$entry['mailquota'] = 0;
-
$entry['alias'] = $user->aliases->pluck('alias')->toArray();
$roles = [];
diff --git a/src/app/Http/Controllers/API/SignupController.php b/src/app/Http/Controllers/API/SignupController.php
--- a/src/app/Http/Controllers/API/SignupController.php
+++ b/src/app/Http/Controllers/API/SignupController.php
@@ -71,26 +71,33 @@
$request->all(),
[
'email' => 'required',
- 'name' => 'required|max:512',
+ 'first_name' => 'max:128',
+ 'last_name' => 'max:128',
'plan' => 'nullable|alpha_num|max:128',
'voucher' => 'max:32',
]
);
- if ($v->fails()) {
- return response()->json(['status' => 'error', 'errors' => $v->errors()], 422);
- }
+ $is_phone = false;
+ $errors = $v->fails() ? $v->errors()->toArray() : [];
// Validate user email (or phone)
- if ($error = $this->validatePhoneOrEmail($request->email, $is_phone)) {
- return response()->json(['status' => 'error', 'errors' => ['email' => $error]], 422);
+ if (empty($errors['email'])) {
+ if ($error = $this->validatePhoneOrEmail($request->email, $is_phone)) {
+ $errors['email'] = $error;
+ }
+ }
+
+ if (!empty($errors)) {
+ return response()->json(['status' => 'error', 'errors' => $errors], 422);
}
// Generate the verification code
$code = SignupCode::create([
'data' => [
'email' => $request->email,
- 'name' => $request->name,
+ 'first_name' => $request->first_name,
+ 'last_name' => $request->last_name,
'plan' => $request->plan,
'voucher' => $request->voucher,
]
@@ -151,7 +158,8 @@
return response()->json([
'status' => 'success',
'email' => $code->data['email'],
- 'name' => $code->data['name'],
+ 'first_name' => $code->data['first_name'],
+ 'last_name' => $code->data['last_name'],
'voucher' => $code->data['voucher'],
'is_domain' => $has_domain,
'domains' => $has_domain ? [] : Domain::getPublicDomains(),
@@ -213,7 +221,6 @@
// Get user name/email from the verification code database
$code_data = $v->getData();
- $user_name = $code_data->name;
$user_email = $code_data->email;
// We allow only ASCII, so we can safely lower-case the email address
@@ -224,7 +231,6 @@
// Create user record
$user = User::create([
- 'name' => $user_name,
'email' => $login . '@' . $domain,
'password' => $request->password,
]);
@@ -248,7 +254,11 @@
$user->assignPlan($plan, $domain);
// Save the external email and plan in user settings
- $user->setSetting('external_email', $user_email);
+ $user->setSettings([
+ 'external_email' => $user_email,
+ 'first_name' => $code_data->first_name,
+ 'last_name' => $code_data->last_name,
+ ]);
// Remove the verification code
$this->code->delete();
diff --git a/src/app/Http/Controllers/API/V4/PaymentsController.php b/src/app/Http/Controllers/API/V4/PaymentsController.php
--- a/src/app/Http/Controllers/API/V4/PaymentsController.php
+++ b/src/app/Http/Controllers/API/V4/PaymentsController.php
@@ -47,7 +47,7 @@
if (empty($customer_id)) {
$customer = mollie()->customers()->create([
- 'name' => $current_user->name,
+ 'name' => $current_user->name(),
'email' => $current_user->email,
]);
diff --git a/src/app/Http/Controllers/API/V4/UsersController.php b/src/app/Http/Controllers/API/V4/UsersController.php
--- a/src/app/Http/Controllers/API/V4/UsersController.php
+++ b/src/app/Http/Controllers/API/V4/UsersController.php
@@ -16,6 +16,18 @@
class UsersController extends Controller
{
+ // List of user settings keys available for modification in UI
+ public const USER_SETTINGS = [
+ 'billing_address',
+ 'country',
+ 'currency',
+ 'external_email',
+ 'first_name',
+ 'last_name',
+ 'organization',
+ 'phone',
+ ];
+
/**
* Delete a user.
*
@@ -178,16 +190,10 @@
return response()->json(['status' => 'error', 'errors' => $errors], 422);
}
- $user_name = !empty($settings['first_name']) ? $settings['first_name'] : '';
- if (!empty($settings['last_name'])) {
- $user_name .= ' ' . $settings['last_name'];
- }
-
DB::beginTransaction();
// Create user record
$user = User::create([
- 'name' => $user_name,
'email' => $request->email,
'password' => $request->password,
]);
@@ -342,10 +348,8 @@
$response = $user->toArray();
// Settings
- // TODO: It might be reasonable to limit the list of settings here to these
- // that are safe and are used in the UI
$response['settings'] = [];
- foreach ($user->settings as $item) {
+ foreach ($user->settings()->whereIn('key', self::USER_SETTINGS)->get() as $item) {
$response['settings'][$item->key] = $item->value;
}
@@ -416,8 +420,9 @@
$rules = [
'external_email' => 'nullable|email',
'phone' => 'string|nullable|max:64|regex:/^[0-9+() -]+$/',
- 'first_name' => 'string|nullable|max:512',
- 'last_name' => 'string|nullable|max:512',
+ 'first_name' => 'string|nullable|max:128',
+ 'last_name' => 'string|nullable|max:128',
+ 'organization' => 'string|nullable|max:512',
'billing_address' => 'string|nullable|max:1024',
'country' => 'string|nullable|alpha|size:2',
'currency' => 'string|nullable|alpha|size:3',
diff --git a/src/app/Mail/PasswordReset.php b/src/app/Mail/PasswordReset.php
--- a/src/app/Mail/PasswordReset.php
+++ b/src/app/Mail/PasswordReset.php
@@ -49,7 +49,7 @@
'code' => $this->code->code,
'short_code' => $this->code->short_code,
'link' => sprintf('<a href="%s">%s</a>', $href, $href),
- 'username' => $this->code->user->name
+ 'username' => $this->code->user->name(true)
]);
return $this;
diff --git a/src/app/Observers/UserObserver.php b/src/app/Observers/UserObserver.php
--- a/src/app/Observers/UserObserver.php
+++ b/src/app/Observers/UserObserver.php
@@ -46,17 +46,30 @@
*/
public function created(User $user)
{
- // FIXME: Actual proper settings
- $user->setSettings(
- [
- 'country' => 'CH',
- 'currency' => 'CHF',
- 'first_name' => '',
- 'last_name' => '',
- 'billing_address' => '',
- 'organization' => ''
- ]
- );
+ $settings = [
+ 'country' => 'CH',
+ 'currency' => 'CHF',
+ /*
+ 'first_name' => '',
+ 'last_name' => '',
+ 'billing_address' => '',
+ 'organization' => '',
+ 'phone' => '',
+ 'external_email' => '',
+ */
+ ];
+
+ foreach ($settings as $key => $value) {
+ $settings[$key] = [
+ 'key' => $key,
+ 'value' => $value,
+ 'user_id' => $user->id,
+ ];
+ }
+
+ // Note: Don't use setSettings() here to bypass UserSetting observers
+ // Note: This is a single multi-insert query
+ $user->settings()->insert(array_values($settings));
$user->wallets()->create();
diff --git a/src/app/Observers/UserSettingObserver.php b/src/app/Observers/UserSettingObserver.php
--- a/src/app/Observers/UserSettingObserver.php
+++ b/src/app/Observers/UserSettingObserver.php
@@ -2,6 +2,7 @@
namespace App\Observers;
+use App\Backends\LDAP;
use App\UserSetting;
class UserSettingObserver
@@ -9,55 +10,42 @@
/**
* Handle the user setting "created" event.
*
- * @param \App\UserSetting $userSetting
+ * @param \App\UserSetting $userSetting Settings object
+ *
* @return void
*/
public function created(UserSetting $userSetting)
{
- //
+ if (in_array($userSetting->key, LDAP::USER_SETTINGS)) {
+ \App\Jobs\UserUpdate::dispatch($userSetting->user);
+ }
}
/**
* Handle the user setting "updated" event.
*
- * @param \App\UserSetting $userSetting
+ * @param \App\UserSetting $userSetting Settings object
+ *
* @return void
*/
public function updated(UserSetting $userSetting)
{
- \App\Jobs\UserUpdate::dispatch($userSetting->user);
+ if (in_array($userSetting->key, LDAP::USER_SETTINGS)) {
+ \App\Jobs\UserUpdate::dispatch($userSetting->user);
+ }
}
/**
* Handle the user setting "deleted" event.
*
- * @param \App\UserSetting $userSetting
- * @return void
- */
- public function deleted(UserSetting $userSetting)
- {
- //
- }
-
- /**
- * Handle the user setting "restored" event.
+ * @param \App\UserSetting $userSetting Settings object
*
- * @param \App\UserSetting $userSetting
* @return void
*/
- public function restored(UserSetting $userSetting)
- {
- //
- }
-
- /**
- * Handle the user setting "force deleted" event.
- *
- * @param \App\UserSetting $userSetting
- * @return void
- */
- public function forceDeleted(UserSetting $userSetting)
+ public function deleted(UserSetting $userSetting)
{
- //
+ if (in_array($userSetting->key, LDAP::USER_SETTINGS)) {
+ \App\Jobs\UserUpdate::dispatch($userSetting->user);
+ }
}
}
diff --git a/src/app/Traits/UserSettingsTrait.php b/src/app/Traits/UserSettingsTrait.php
--- a/src/app/Traits/UserSettingsTrait.php
+++ b/src/app/Traits/UserSettingsTrait.php
@@ -81,7 +81,9 @@
private function storeSetting(string $key, $value): void
{
if ($value === null || $value === '') {
- UserSetting::where(['user_id' => $this->id, 'key' => $key])->delete();
+ if ($setting = UserSetting::where(['user_id' => $this->id, 'key' => $key])->first()) {
+ $setting->delete();
+ }
} else {
UserSetting::updateOrCreate(
['user_id' => $this->id, 'key' => $key],
diff --git a/src/app/User.php b/src/app/User.php
--- a/src/app/User.php
+++ b/src/app/User.php
@@ -8,7 +8,6 @@
use App\Traits\UserSettingsTrait;
use App\Wallet;
use Illuminate\Notifications\Notifiable;
-use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Iatstuti\Database\Support\NullableFields;
@@ -19,7 +18,6 @@
*
* @property string $email
* @property int $id
- * @property string $name
* @property string $password
* @property int $status
*/
@@ -55,7 +53,6 @@
* @var array
*/
protected $fillable = [
- 'name',
'email',
'password',
'password_ldap',
@@ -70,26 +67,15 @@
protected $hidden = [
'password',
'password_ldap',
- 'remember_token',
'role'
];
protected $nullable = [
- 'name',
'password',
'password_ldap'
];
/**
- * The attributes that should be cast to native types.
- *
- * @var array
- */
- protected $casts = [
- 'email_verified_at' => 'datetime',
- ];
-
- /**
* Any wallets on which this user is a controller.
*
* This does not include wallets owned by the user.
@@ -457,6 +443,27 @@
}
/**
+ * A shortcut to get the user name.
+ *
+ * @param bool $fallback Return "<aa.name> User" if there's no name
+ *
+ * @return string Full user name
+ */
+ public function name(bool $fallback = false): string
+ {
+ $firstname = $this->getSetting('first_name');
+ $lastname = $this->getSetting('last_name');
+
+ $name = trim($firstname . ' ' . $lastname);
+
+ if (empty($name) && $fallback) {
+ return \config('app.name') . ' User';
+ }
+
+ return $name;
+ }
+
+ /**
* Any (additional) properties of this user.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
diff --git a/src/composer.json b/src/composer.json
--- a/src/composer.json
+++ b/src/composer.json
@@ -42,7 +42,7 @@
"nunomaduro/collision": "^3.0",
"nunomaduro/larastan": "^0.4",
"phpstan/phpstan": "0.11.19",
- "phpunit/phpunit": "^7.5"
+ "phpunit/phpunit": "^8"
},
"config": {
"optimize-autoloader": true,
diff --git a/src/database/factories/UserFactory.php b/src/database/factories/UserFactory.php
--- a/src/database/factories/UserFactory.php
+++ b/src/database/factories/UserFactory.php
@@ -20,9 +20,7 @@
User::class,
function (Faker $faker) {
return [
- 'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
- 'email_verified_at' => now(),
'password' => Str::random(64)
];
}
diff --git a/src/database/migrations/2014_10_12_000000_create_users_table.php b/src/database/migrations/2014_10_12_000000_create_users_table.php
--- a/src/database/migrations/2014_10_12_000000_create_users_table.php
+++ b/src/database/migrations/2014_10_12_000000_create_users_table.php
@@ -17,13 +17,11 @@
'users',
function (Blueprint $table) {
$table->bigInteger('id');
- $table->string('name')->nullable();
$table->string('email')->unique();
- $table->timestamp('email_verified_at')->nullable();
$table->string('password')->nullable();
$table->string('password_ldap')->nullable();
$table->smallinteger('status');
- $table->rememberToken();
+// $table->rememberToken();
$table->timestamps();
$table->primary('id');
diff --git a/src/database/seeds/UserSeeder.php b/src/database/seeds/UserSeeder.php
--- a/src/database/seeds/UserSeeder.php
+++ b/src/database/seeds/UserSeeder.php
@@ -32,10 +32,8 @@
$john = User::create(
[
- 'name' => 'John Doe',
'email' => 'john@kolab.org',
'password' => 'simple123',
- 'email_verified_at' => now()
]
);
@@ -47,6 +45,7 @@
'country' => 'US',
'billing_address' => "601 13th Street NW\nSuite 900 South\nWashington, DC 20005",
'external_email' => 'john.doe.external@gmail.com',
+ 'organization' => 'Kolab Developers',
'phone' => '+1 509-248-1111',
]
);
@@ -64,10 +63,8 @@
$jack = User::create(
[
- 'name' => 'Jack Daniels',
'email' => 'jack@kolab.org',
'password' => 'simple123',
- 'email_verified_at' => now()
]
);
@@ -92,10 +89,8 @@
$ned = User::create(
[
- 'name' => 'Edward Flanders',
'email' => 'ned@kolab.org',
'password' => 'simple123',
- 'email_verified_at' => now()
]
);
@@ -122,10 +117,8 @@
$joe = User::create(
[
- 'name' => 'Joe Sixpack',
'email' => 'joe@kolab.org',
'password' => 'simple123',
- 'email_verified_at' => now()
]
);
@@ -135,10 +128,8 @@
$jeroen = User::create(
[
- 'name' => 'Jeroen van Meeuwen',
'email' => 'jeroen@jeroen.jeroen',
'password' => 'jeroen',
- 'email_verified_at' => now()
]
);
diff --git a/src/resources/vue/Admin/User.vue b/src/resources/vue/Admin/User.vue
--- a/src/resources/vue/Admin/User.vue
+++ b/src/resources/vue/Admin/User.vue
@@ -41,6 +41,12 @@
<span class="form-control-plaintext" id="last_name">{{ user.last_name }}</span>
</div>
</div>
+ <div class="form-group row mb-0" v-if="user.organization">
+ <label for="organization" class="col-sm-4 col-form-label">Organization</label>
+ <div class="col-sm-8">
+ <span class="form-control-plaintext" id="organization">{{ user.organization }}</span>
+ </div>
+ </div>
<div class="form-group row mb-0" v-if="user.phone">
<label for="phone" class="col-sm-4 col-form-label">Phone</label>
<div class="col-sm-8">
@@ -106,7 +112,7 @@
<div class="card-text">
<form>
<div class="form-group row mb-0">
- <label for="first_name" class="col-sm-2 col-form-label">Discount:</label>
+ <label class="col-sm-2 col-form-label">Discount:</label>
<div class="col-sm-10">
<span class="form-control-plaintext" id="discount">
<span>{{ wallet_discount ? (wallet_discount + '% - ' + wallet_discount_description) : 'none' }}</span>
@@ -292,7 +298,7 @@
this.user = response.data
- let keys = ['first_name', 'last_name', 'external_email', 'billing_address', 'phone']
+ let keys = ['first_name', 'last_name', 'external_email', 'billing_address', 'phone', 'organization']
let country = this.user.settings.country
if (country) {
diff --git a/src/resources/vue/Signup.vue b/src/resources/vue/Signup.vue
--- a/src/resources/vue/Signup.vue
+++ b/src/resources/vue/Signup.vue
@@ -26,8 +26,10 @@
</p>
<form @submit.prevent="submitStep1" data-validation-prefix="signup_">
<div class="form-group">
- <label for="signup_name" class="sr-only">Your Name</label>
- <input type="text" class="form-control" id="signup_name" placeholder="Your Name" required autofocus v-model="name">
+ <div class="input-group">
+ <input type="text" class="form-control" id="signup_first_name" placeholder="First Name" autofocus v-model="first_name">
+ <input type="text" class="form-control rounded-right" id="signup_last_name" placeholder="Surname" v-model="last_name">
+ </div>
</div>
<div class="form-group">
<label for="signup_email" class="sr-only">Existing Email Address</label>
@@ -101,7 +103,8 @@
data() {
return {
email: '',
- name: '',
+ first_name: '',
+ last_name: '',
code: '',
short_code: '',
login: '',
@@ -162,7 +165,8 @@
axios.post('/api/auth/signup/init', {
email: this.email,
- name: this.name,
+ last_name: this.last_name,
+ first_name: this.first_name,
plan: this.plan,
voucher: this.voucher
}).then(response => {
@@ -184,7 +188,8 @@
}).then(response => {
this.displayForm(3, true)
// Reset user name/email/plan, we don't have them if user used a verification link
- this.name = response.data.name
+ this.first_name = response.data.first_name
+ this.last_name = response.data.last_name
this.email = response.data.email
this.is_domain = response.data.is_domain
this.voucher = response.data.voucher
diff --git a/src/resources/vue/User/Info.vue b/src/resources/vue/User/Info.vue
--- a/src/resources/vue/User/Info.vue
+++ b/src/resources/vue/User/Info.vue
@@ -25,6 +25,12 @@
</div>
</div>
<div class="form-group row">
+ <label for="organization" class="col-sm-4 col-form-label">Organization</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" id="organization" v-model="user.organization">
+ </div>
+ </div>
+ <div class="form-group row">
<label for="email" class="col-sm-4 col-form-label">Email</label>
<div class="col-sm-8">
<input type="text" class="form-control" id="email" :disabled="user_id !== 'new'" required v-model="user.email">
@@ -193,6 +199,7 @@
this.user = response.data
this.user.first_name = response.data.settings.first_name
this.user.last_name = response.data.settings.last_name
+ this.user.organization = response.data.settings.organization
this.discount = this.user.wallet.discount
this.discount_description = this.user.wallet.discount_description
diff --git a/src/resources/vue/User/Profile.vue b/src/resources/vue/User/Profile.vue
--- a/src/resources/vue/User/Profile.vue
+++ b/src/resources/vue/User/Profile.vue
@@ -18,6 +18,12 @@
</div>
</div>
<div class="form-group row">
+ <label for="organization" class="col-sm-4 col-form-label">Organization</label>
+ <div class="col-sm-8">
+ <input type="text" class="form-control" id="organization" v-model="profile.organization">
+ </div>
+ </div>
+ <div class="form-group row">
<label for="phone" class="col-sm-4 col-form-label">Phone</label>
<div class="col-sm-8">
<input type="text" class="form-control" id="phone" v-model="profile.phone">
diff --git a/src/tests/Browser/Admin/UserTest.php b/src/tests/Browser/Admin/UserTest.php
--- a/src/tests/Browser/Admin/UserTest.php
+++ b/src/tests/Browser/Admin/UserTest.php
@@ -180,7 +180,7 @@
->with('@user-info form', function (Browser $browser) use ($john) {
$ext_email = $john->getSetting('external_email');
- $browser->assertElementsCount('.row', 8)
+ $browser->assertElementsCount('.row', 9)
->assertSeeIn('.row:nth-child(1) label', 'ID (Created at)')
->assertSeeIn('.row:nth-child(1) #userid', "{$john->id} ({$john->created_at})")
->assertSeeIn('.row:nth-child(2) label', 'Status')
@@ -189,15 +189,17 @@
->assertSeeIn('.row:nth-child(3) #first_name', 'John')
->assertSeeIn('.row:nth-child(4) label', 'Last name')
->assertSeeIn('.row:nth-child(4) #last_name', 'Doe')
- ->assertSeeIn('.row:nth-child(5) label', 'Phone')
- ->assertSeeIn('.row:nth-child(5) #phone', $john->getSetting('phone'))
- ->assertSeeIn('.row:nth-child(6) label', 'External email')
- ->assertSeeIn('.row:nth-child(6) #external_email a', $ext_email)
- ->assertAttribute('.row:nth-child(6) #external_email a', 'href', "mailto:$ext_email")
- ->assertSeeIn('.row:nth-child(7) label', 'Address')
- ->assertSeeIn('.row:nth-child(7) #billing_address', $john->getSetting('billing_address'))
- ->assertSeeIn('.row:nth-child(8) label', 'Country')
- ->assertSeeIn('.row:nth-child(8) #country', 'United States of America');
+ ->assertSeeIn('.row:nth-child(5) label', 'Organization')
+ ->assertSeeIn('.row:nth-child(5) #organization', 'Kolab Developers')
+ ->assertSeeIn('.row:nth-child(6) label', 'Phone')
+ ->assertSeeIn('.row:nth-child(6) #phone', $john->getSetting('phone'))
+ ->assertSeeIn('.row:nth-child(7) label', 'External email')
+ ->assertSeeIn('.row:nth-child(7) #external_email a', $ext_email)
+ ->assertAttribute('.row:nth-child(7) #external_email a', 'href', "mailto:$ext_email")
+ ->assertSeeIn('.row:nth-child(8) label', 'Address')
+ ->assertSeeIn('.row:nth-child(8) #billing_address', $john->getSetting('billing_address'))
+ ->assertSeeIn('.row:nth-child(9) label', 'Country')
+ ->assertSeeIn('.row:nth-child(9) #country', 'United States of America');
});
// Some tabs are loaded in background, wait a second
diff --git a/src/tests/Browser/SignupTest.php b/src/tests/Browser/SignupTest.php
--- a/src/tests/Browser/SignupTest.php
+++ b/src/tests/Browser/SignupTest.php
@@ -74,7 +74,8 @@
$code = SignupCode::create([
'data' => [
'email' => 'User@example.org',
- 'name' => 'User Name',
+ 'first_name' => 'User',
+ 'last_name' => 'Name',
'plan' => 'individual',
'voucher' => '',
]
@@ -125,7 +126,7 @@
->assertMissing('@step0')
->assertMissing('@step2')
->assertMissing('@step3')
- ->assertFocused('@step1 #signup_name');
+ ->assertFocused('@step1 #signup_first_name');
// Click Back button
$browser->click('@step1 [type=button]')
@@ -142,7 +143,7 @@
->assertMissing('@step0')
->assertMissing('@step2')
->assertMissing('@step3')
- ->assertFocused('@step1 #signup_name');
+ ->assertFocused('@step1 #signup_first_name');
// TODO: Test if 'plan' variable is set properly in vue component
});
@@ -165,41 +166,44 @@
// Here we expect two text inputs and Back and Continue buttons
$browser->with('@step1', function ($step) {
- $step->assertVisible('#signup_name')
- ->assertFocused('#signup_name')
+ $step->assertVisible('#signup_last_name')
+ ->assertVisible('#signup_first_name')
+ ->assertFocused('#signup_first_name')
->assertVisible('#signup_email')
->assertVisible('[type=button]')
->assertVisible('[type=submit]');
});
// Submit empty form
- // Both Step 1 inputs are required, so after pressing Submit
- // we expect focus to be moved to the first input
+ // Email is required, so after pressing Submit
+ // we expect focus to be moved to the email input
$browser->with('@step1', function ($step) {
$step->click('[type=submit]');
- $step->assertFocused('#signup_name');
+ $step->assertFocused('#signup_email');
});
- // Submit invalid email
- // We expect email input to have is-invalid class added, with .invalid-feedback element
+ // Submit invalid email, and first_name
+ // We expect both inputs to have is-invalid class added, with .invalid-feedback element
$browser->with('@step1', function ($step) use ($browser) {
- $step->type('#signup_name', 'Test User')
+ $step->type('#signup_first_name', str_repeat('a', 250))
->type('#signup_email', '@test')
->click('[type=submit]')
->waitFor('#signup_email.is-invalid')
+ ->assertVisible('#signup_first_name.is-invalid')
->assertVisible('#signup_email + .invalid-feedback')
+ ->assertVisible('#signup_last_name + .invalid-feedback')
->assertToast(Toast::TYPE_ERROR, 'Form validation error');
});
// Submit valid data
// We expect error state on email input to be removed, and Step 2 form visible
$browser->with('@step1', function ($step) {
- $step->type('#signup_name', 'Test User');
- $step->type('#signup_email', 'BrowserSignupTestUser1@kolab.org');
- $step->click('[type=submit]');
-
- $step->assertMissing('#signup_email.is-invalid');
- $step->assertMissing('#signup_email + .invalid-feedback');
+ $step->type('#signup_first_name', 'Test')
+ ->type('#signup_last_name', 'User')
+ ->type('#signup_email', 'BrowserSignupTestUser1@kolab.org')
+ ->click('[type=submit]')
+ ->assertMissing('#signup_email.is-invalid')
+ ->assertMissing('#signup_email + .invalid-feedback');
});
$browser->waitUntilMissing('@step2 #signup_code[value=""]');
@@ -232,14 +236,15 @@
// Test Back button functionality
$browser->click('@step2 [type=button]')
->waitFor('@step1')
- ->assertFocused('@step1 #signup_name')
+ ->assertFocused('@step1 #signup_first_name')
->assertMissing('@step2');
// Submit valid Step 1 data (again)
$browser->with('@step1', function ($step) {
- $step->type('#signup_name', 'Test User');
- $step->type('#signup_email', 'BrowserSignupTestUser1@kolab.org');
- $step->click('[type=submit]');
+ $step->type('#signup_first_name', 'User')
+ ->type('#signup_last_name', 'User')
+ ->type('#signup_email', 'BrowserSignupTestUser1@kolab.org')
+ ->click('[type=submit]');
});
$browser->waitFor('@step2');
@@ -389,7 +394,8 @@
// Submit valid data
// We expect error state on email input to be removed, and Step 2 form visible
$browser->whenAvailable('@step1', function ($step) {
- $step->type('#signup_name', 'Test User')
+ $step->type('#signup_first_name', 'Test')
+ ->type('#signup_last_name', 'User')
->type('#signup_email', 'BrowserSignupTestUser1@kolab.org')
->click('[type=submit]');
});
@@ -478,7 +484,8 @@
->waitFor('@step0')
->click('.plan-individual button')
->whenAvailable('@step1', function (Browser $browser) {
- $browser->type('#signup_name', 'Test User')
+ $browser->type('#signup_first_name', 'Test')
+ ->type('#signup_last_name', 'User')
->type('#signup_email', 'BrowserSignupTestUser1@kolab.org')
->click('[type=submit]');
})
diff --git a/src/tests/Browser/UserProfileTest.php b/src/tests/Browser/UserProfileTest.php
--- a/src/tests/Browser/UserProfileTest.php
+++ b/src/tests/Browser/UserProfileTest.php
@@ -21,6 +21,7 @@
'billing_address' => "601 13th Street NW\nSuite 900 South\nWashington, DC 20005",
'external_email' => 'john.doe.external@gmail.com',
'phone' => '+1 509-248-1111',
+ 'organization' => 'Kolab Developers',
];
/**
@@ -76,24 +77,27 @@
->assertValue('div.row:nth-child(1) input[type=text]', $this->profile['first_name'])
->assertSeeIn('div.row:nth-child(2) label', 'Last name')
->assertValue('div.row:nth-child(2) input[type=text]', $this->profile['last_name'])
- ->assertSeeIn('div.row:nth-child(3) label', 'Phone')
- ->assertValue('div.row:nth-child(3) input[type=text]', $this->profile['phone'])
- ->assertSeeIn('div.row:nth-child(4) label', 'External email')
- ->assertValue('div.row:nth-child(4) input[type=text]', $this->profile['external_email'])
- ->assertSeeIn('div.row:nth-child(5) label', 'Address')
- ->assertValue('div.row:nth-child(5) textarea', $this->profile['billing_address'])
- ->assertSeeIn('div.row:nth-child(6) label', 'Country')
- ->assertValue('div.row:nth-child(6) select', $this->profile['country'])
- ->assertSeeIn('div.row:nth-child(7) label', 'Password')
- ->assertValue('div.row:nth-child(7) input[type=password]', '')
- ->assertSeeIn('div.row:nth-child(8) label', 'Confirm password')
+ ->assertSeeIn('div.row:nth-child(3) label', 'Organization')
+ ->assertValue('div.row:nth-child(3) input[type=text]', $this->profile['organization'])
+ ->assertSeeIn('div.row:nth-child(4) label', 'Phone')
+ ->assertValue('div.row:nth-child(4) input[type=text]', $this->profile['phone'])
+ ->assertSeeIn('div.row:nth-child(5) label', 'External email')
+ ->assertValue('div.row:nth-child(5) input[type=text]', $this->profile['external_email'])
+ ->assertSeeIn('div.row:nth-child(6) label', 'Address')
+ ->assertValue('div.row:nth-child(6) textarea', $this->profile['billing_address'])
+ ->assertSeeIn('div.row:nth-child(7) label', 'Country')
+ ->assertValue('div.row:nth-child(7) select', $this->profile['country'])
+ ->assertSeeIn('div.row:nth-child(8) label', 'Password')
->assertValue('div.row:nth-child(8) input[type=password]', '')
+ ->assertSeeIn('div.row:nth-child(9) label', 'Confirm password')
+ ->assertValue('div.row:nth-child(9) input[type=password]', '')
->assertSeeIn('button[type=submit]', 'Submit');
// Clear all fields and submit
// FIXME: Should any of these fields be required?
$browser->type('#first_name', '')
->type('#last_name', '')
+ ->type('#organization', '')
->type('#phone', '')
->type('#external_email', '')
->type('#billing_address', '')
diff --git a/src/tests/Browser/UsersTest.php b/src/tests/Browser/UsersTest.php
--- a/src/tests/Browser/UsersTest.php
+++ b/src/tests/Browser/UsersTest.php
@@ -24,6 +24,7 @@
private $profile = [
'first_name' => 'John',
'last_name' => 'Doe',
+ 'organization' => 'Kolab Developers',
];
/**
@@ -140,19 +141,21 @@
->assertValue('div.row:nth-child(2) input[type=text]', $this->profile['first_name'])
->assertSeeIn('div.row:nth-child(3) label', 'Last name')
->assertValue('div.row:nth-child(3) input[type=text]', $this->profile['last_name'])
- ->assertSeeIn('div.row:nth-child(4) label', 'Email')
- ->assertValue('div.row:nth-child(4) input[type=text]', 'john@kolab.org')
- ->assertDisabled('div.row:nth-child(4) input[type=text]')
- ->assertSeeIn('div.row:nth-child(5) label', 'Email aliases')
- ->assertVisible('div.row:nth-child(5) .list-input')
+ ->assertSeeIn('div.row:nth-child(4) label', 'Organization')
+ ->assertValue('div.row:nth-child(4) input[type=text]', $this->profile['organization'])
+ ->assertSeeIn('div.row:nth-child(5) label', 'Email')
+ ->assertValue('div.row:nth-child(5) input[type=text]', 'john@kolab.org')
+ ->assertDisabled('div.row:nth-child(5) input[type=text]')
+ ->assertSeeIn('div.row:nth-child(6) label', 'Email aliases')
+ ->assertVisible('div.row:nth-child(6) .list-input')
->with(new ListInput('#aliases'), function (Browser $browser) {
$browser->assertListInputValue(['john.doe@kolab.org'])
->assertValue('@input', '');
})
- ->assertSeeIn('div.row:nth-child(6) label', 'Password')
- ->assertValue('div.row:nth-child(6) input[type=password]', '')
- ->assertSeeIn('div.row:nth-child(7) label', 'Confirm password')
+ ->assertSeeIn('div.row:nth-child(7) label', 'Password')
->assertValue('div.row:nth-child(7) input[type=password]', '')
+ ->assertSeeIn('div.row:nth-child(8) label', 'Confirm password')
+ ->assertValue('div.row:nth-child(8) input[type=password]', '')
->assertSeeIn('button[type=submit]', 'Submit');
// Clear some fields and submit
@@ -210,8 +213,8 @@
// Test subscriptions
$browser->with('@form', function (Browser $browser) {
- $browser->assertSeeIn('div.row:nth-child(8) label', 'Subscriptions')
- ->assertVisible('@skus.row:nth-child(8)')
+ $browser->assertSeeIn('div.row:nth-child(9) label', 'Subscriptions')
+ ->assertVisible('@skus.row:nth-child(9)')
->with('@skus', function ($browser) {
$browser->assertElementsCount('tbody tr', 5)
// Mailbox SKU
@@ -321,20 +324,22 @@
->assertValue('div.row:nth-child(1) input[type=text]', '')
->assertSeeIn('div.row:nth-child(2) label', 'Last name')
->assertValue('div.row:nth-child(2) input[type=text]', '')
- ->assertSeeIn('div.row:nth-child(3) label', 'Email')
+ ->assertSeeIn('div.row:nth-child(3) label', 'Organization')
->assertValue('div.row:nth-child(3) input[type=text]', '')
- ->assertEnabled('div.row:nth-child(3) input[type=text]')
- ->assertSeeIn('div.row:nth-child(4) label', 'Email aliases')
- ->assertVisible('div.row:nth-child(4) .list-input')
+ ->assertSeeIn('div.row:nth-child(4) label', 'Email')
+ ->assertValue('div.row:nth-child(4) input[type=text]', '')
+ ->assertEnabled('div.row:nth-child(4) input[type=text]')
+ ->assertSeeIn('div.row:nth-child(5) label', 'Email aliases')
+ ->assertVisible('div.row:nth-child(5) .list-input')
->with(new ListInput('#aliases'), function (Browser $browser) {
$browser->assertListInputValue([])
->assertValue('@input', '');
})
- ->assertSeeIn('div.row:nth-child(5) label', 'Password')
- ->assertValue('div.row:nth-child(5) input[type=password]', '')
- ->assertSeeIn('div.row:nth-child(6) label', 'Confirm password')
+ ->assertSeeIn('div.row:nth-child(6) label', 'Password')
->assertValue('div.row:nth-child(6) input[type=password]', '')
- ->assertSeeIn('div.row:nth-child(7) label', 'Package')
+ ->assertSeeIn('div.row:nth-child(7) label', 'Confirm password')
+ ->assertValue('div.row:nth-child(7) input[type=password]', '')
+ ->assertSeeIn('div.row:nth-child(8) label', 'Package')
// assert packages list widget, select "Lite Account"
->with('@packages', function ($browser) {
$browser->assertElementsCount('tbody tr', 2)
@@ -382,10 +387,13 @@
// Successful account creation
$browser->with('@form', function (Browser $browser) {
- $browser->with(new ListInput('#aliases'), function (Browser $browser) {
- $browser->removeListEntry(1)
- ->addListEntry('julia.roberts2@kolab.org');
- })
+ $browser->type('#first_name', 'Julia')
+ ->type('#last_name', 'Roberts')
+ ->type('#organization', 'Test Org')
+ ->with(new ListInput('#aliases'), function (Browser $browser) {
+ $browser->removeListEntry(1)
+ ->addListEntry('julia.roberts2@kolab.org');
+ })
->click('button[type=submit]');
})
->assertToast(Toast::TYPE_SUCCESS, 'User created successfully.')
@@ -401,6 +409,9 @@
$alias = UserAlias::where('user_id', $julia->id)->where('alias', 'julia.roberts2@kolab.org')->first();
$this->assertTrue(!empty($alias));
$this->assertUserEntitlements($julia, ['mailbox', 'storage', 'storage']);
+ $this->assertSame('Julia', $julia->getSetting('first_name'));
+ $this->assertSame('Roberts', $julia->getSetting('last_name'));
+ $this->assertSame('Test Org', $julia->getSetting('organization'));
});
}
diff --git a/src/tests/Feature/Backends/LDAPTest.php b/src/tests/Feature/Backends/LDAPTest.php
--- a/src/tests/Feature/Backends/LDAPTest.php
+++ b/src/tests/Feature/Backends/LDAPTest.php
@@ -4,48 +4,151 @@
use App\Backends\LDAP;
use App\Domain;
+use App\Entitlement;
use App\User;
+use Illuminate\Support\Facades\Queue;
use Tests\TestCase;
class LDAPTest extends TestCase
{
/**
- * Test creating a domain record
- *
- * @group ldap
+ * {@inheritDoc}
*/
- public function testCreateDomain(): void
+ public function setUp(): void
{
- $this->markTestIncomplete();
+ parent::setUp();
+
+ $this->deleteTestUser('user-ldap-test@' . \config('app.domain'));
}
/**
- * Test creating a user record
- *
- * @group ldap
+ * {@inheritDoc}
*/
- public function testCreateUser(): void
+ public function tearDown(): void
{
- $this->markTestIncomplete();
+ $this->deleteTestUser('user-ldap-test@' . \config('app.domain'));
+
+ parent::tearDown();
}
/**
- * Test updating a domain record
+ * Test creating/updating/deleting a domain record
*
* @group ldap
*/
- public function testUpdateDomain(): void
+ public function testDomain(): void
{
$this->markTestIncomplete();
}
/**
- * Test updating a user record
+ * Test creating/editing/deleting a user record
*
* @group ldap
*/
- public function testUpdateUser(): void
+ public function testUser(): void
{
- $this->markTestIncomplete();
+ Queue::fake();
+
+ $user = $this->getTestUser('user-ldap-test@' . \config('app.domain'));
+
+ LDAP::createUser($user);
+
+ $ldap_user = LDAP::getUser($user->email);
+
+ $expected = [
+ 'objectclass' => [
+ 'top',
+ 'inetorgperson',
+ 'inetuser',
+ 'kolabinetorgperson',
+ 'mailrecipient',
+ 'person',
+ 'organizationalPerson',
+ ],
+ 'mail' => $user->email,
+ 'uid' => $user->email,
+ 'nsroledn' => null,
+ 'cn' => 'unknown',
+ 'displayname' => '',
+ 'givenname' => '',
+ 'sn' => 'unknown',
+ 'inetuserstatus' => $user->status,
+ 'mailquota' => null,
+ 'o' => '',
+ 'alias' => null,
+ ];
+
+ foreach ($expected as $attr => $value) {
+ $this->assertEquals($value, isset($ldap_user[$attr]) ? $ldap_user[$attr] : null);
+ }
+
+ // Add aliases, and change some user settings, and entitlements
+ $user->setSettings([
+ 'first_name' => 'Firstname',
+ 'last_name' => 'Lastname',
+ 'organization' => 'Org',
+ 'country' => 'PL',
+ ]);
+ $user->status |= User::STATUS_IMAP_READY;
+ $user->save();
+ $aliases = ['t1-' . $user->email, 't2-' . $user->email];
+ $user->setAliases($aliases);
+ $package_kolab = \App\Package::where('title', 'kolab')->first();
+ $user->assignPackage($package_kolab);
+
+ LDAP::updateUser($user->fresh());
+
+ $expected['alias'] = $aliases;
+ $expected['o'] = 'Org';
+ $expected['displayname'] = 'Lastname, Firstname';
+ $expected['givenname'] = 'Firstname';
+ $expected['cn'] = 'Firstname Lastname';
+ $expected['sn'] = 'Lastname';
+ $expected['inetuserstatus'] = $user->status;
+ $expected['mailquota'] = 2097152;
+ $expected['nsroledn'] = null;
+ // TODO: country? dn
+
+ $ldap_user = LDAP::getUser($user->email);
+
+ foreach ($expected as $attr => $value) {
+ $this->assertEquals($value, isset($ldap_user[$attr]) ? $ldap_user[$attr] : null);
+ }
+
+ // Update entitlements
+ $sku_activesync = \App\Sku::where('title', 'activesync')->first();
+ $sku_groupware = \App\Sku::where('title', 'groupware')->first();
+ $user->assignSku($sku_activesync, 1);
+ Entitlement::where(['sku_id' => $sku_groupware->id, 'entitleable_id' => $user->id])->delete();
+
+ LDAP::updateUser($user->fresh());
+
+ $expected_roles = [
+ 'activesync-user',
+ 'imap-user'
+ ];
+
+ $ldap_user = LDAP::getUser($user->email);
+
+ $this->assertCount(2, $ldap_user['nsroledn']);
+
+ $ldap_roles = array_map(
+ function ($role) {
+ if (preg_match('/^cn=([a-z0-9-]+)/', $role, $m)) {
+ return $m[1];
+ } else {
+ return $role;
+ }
+ },
+ $ldap_user['nsroledn']
+ );
+
+ $this->assertSame($expected_roles, $ldap_roles);
+
+ // Delete the user
+ LDAP::deleteUser($user);
+
+ $this->assertSame(null, LDAP::getUser($user->email));
}
}
diff --git a/src/tests/Feature/Controller/SignupTest.php b/src/tests/Feature/Controller/SignupTest.php
--- a/src/tests/Feature/Controller/SignupTest.php
+++ b/src/tests/Feature/Controller/SignupTest.php
@@ -107,13 +107,14 @@
$response->assertStatus(422);
$this->assertSame('error', $json['status']);
- $this->assertCount(2, $json['errors']);
+ $this->assertCount(1, $json['errors']);
$this->assertArrayHasKey('email', $json['errors']);
- $this->assertArrayHasKey('name', $json['errors']);
// Data with missing name
$data = [
'email' => 'UsersApiControllerTest1@UsersApiControllerTest.com',
+ 'first_name' => str_repeat('a', 250),
+ 'last_name' => str_repeat('a', 250),
];
$response = $this->post('/api/auth/signup/init', $data);
@@ -122,13 +123,15 @@
$response->assertStatus(422);
$this->assertSame('error', $json['status']);
- $this->assertCount(1, $json['errors']);
- $this->assertArrayHasKey('name', $json['errors']);
+ $this->assertCount(2, $json['errors']);
+ $this->assertArrayHasKey('first_name', $json['errors']);
+ $this->assertArrayHasKey('last_name', $json['errors']);
// Data with invalid email (but not phone number)
$data = [
'email' => '@example.org',
- 'name' => 'Signup User',
+ 'first_name' => 'Signup',
+ 'last_name' => 'User',
];
$response = $this->post('/api/auth/signup/init', $data);
@@ -140,10 +143,9 @@
$this->assertCount(1, $json['errors']);
$this->assertArrayHasKey('email', $json['errors']);
- // Sanity check on voucher code
+ // Sanity check on voucher code, last/first name is optional
$data = [
'voucher' => '123456789012345678901234567890123',
- 'name' => 'Signup User',
'email' => 'valid@email.com',
];
@@ -173,7 +175,8 @@
$data = [
'email' => 'testuser@external.com',
- 'name' => 'Signup User',
+ 'first_name' => 'Signup',
+ 'last_name' => 'User',
'plan' => 'individual',
];
@@ -195,7 +198,8 @@
return $code->code === $json['code']
&& $code->data['plan'] === $data['plan']
&& $code->data['email'] === $data['email']
- && $code->data['name'] === $data['name'];
+ && $code->data['first_name'] === $data['first_name']
+ && $code->data['last_name'] === $data['last_name'];
});
// Try the same with voucher
@@ -217,13 +221,15 @@
&& $code->data['plan'] === $data['plan']
&& $code->data['email'] === $data['email']
&& $code->data['voucher'] === $data['voucher']
- && $code->data['name'] === $data['name'];
+ && $code->data['first_name'] === $data['first_name']
+ && $code->data['last_name'] === $data['last_name'];
});
return [
'code' => $json['code'],
'email' => $data['email'],
- 'name' => $data['name'],
+ 'first_name' => $data['first_name'],
+ 'last_name' => $data['last_name'],
'plan' => $data['plan'],
'voucher' => $data['voucher']
];
@@ -298,10 +304,11 @@
$json = $response->json();
$response->assertStatus(200);
- $this->assertCount(6, $json);
+ $this->assertCount(7, $json);
$this->assertSame('success', $json['status']);
$this->assertSame($result['email'], $json['email']);
- $this->assertSame($result['name'], $json['name']);
+ $this->assertSame($result['first_name'], $json['first_name']);
+ $this->assertSame($result['last_name'], $json['last_name']);
$this->assertSame($result['voucher'], $json['voucher']);
$this->assertSame(false, $json['is_domain']);
$this->assertTrue(is_array($json['domains']) && !empty($json['domains']));
@@ -489,9 +496,10 @@
$this->assertNotEmpty($user);
$this->assertSame($identity, $user->email);
- $this->assertSame($result['name'], $user->name);
- // Check external email in user settings
+ // Check user settings
+ $this->assertSame($result['first_name'], $user->getSetting('first_name'));
+ $this->assertSame($result['last_name'], $user->getSetting('last_name'));
$this->assertSame($result['email'], $user->getSetting('external_email'));
// Discount
@@ -515,7 +523,8 @@
// Initial signup request
$user_data = $data = [
'email' => 'testuser@external.com',
- 'name' => 'Signup User',
+ 'first_name' => 'Signup',
+ 'last_name' => 'User',
'plan' => 'group',
];
@@ -537,7 +546,8 @@
return $code->code === $json['code']
&& $code->data['plan'] === $data['plan']
&& $code->data['email'] === $data['email']
- && $code->data['name'] === $data['name'];
+ && $code->data['first_name'] === $data['first_name']
+ && $code->data['last_name'] === $data['last_name'];
});
// Verify the code
@@ -551,10 +561,11 @@
$result = $response->json();
$response->assertStatus(200);
- $this->assertCount(6, $result);
+ $this->assertCount(7, $result);
$this->assertSame('success', $result['status']);
$this->assertSame($user_data['email'], $result['email']);
- $this->assertSame($user_data['name'], $result['name']);
+ $this->assertSame($user_data['first_name'], $result['first_name']);
+ $this->assertSame($user_data['last_name'], $result['last_name']);
$this->assertSame(null, $result['voucher']);
$this->assertSame(true, $result['is_domain']);
$this->assertSame([], $result['domains']);
@@ -602,12 +613,13 @@
$user = User::where('email', $login . '@' . $domain)->first();
$this->assertNotEmpty($user);
- $this->assertSame($user_data['name'], $user->name);
-
- // Check domain record
- // Check external email in user settings
+ // Check user settings
$this->assertSame($user_data['email'], $user->getSetting('external_email'));
+ $this->assertSame($user_data['first_name'], $user->getSetting('first_name'));
+ $this->assertSame($user_data['last_name'], $user->getSetting('last_name'));
+
+ // TODO: Check domain record
// TODO: Check SKUs/Plan
diff --git a/src/tests/Feature/Controller/UsersTest.php b/src/tests/Feature/Controller/UsersTest.php
--- a/src/tests/Feature/Controller/UsersTest.php
+++ b/src/tests/Feature/Controller/UsersTest.php
@@ -139,7 +139,7 @@
// TODO/FIXME:
// For now controller can delete himself, as well as
// the whole account he has control to, including the owner
- // Probably he should not be able to do either of those
+ // Probably he should not be able to do none of those
// However, this is not 0-regression scenario as we
// do not fully support additional controllers.
@@ -290,6 +290,7 @@
$this->assertTrue(is_array($result['settings']));
$this->assertSame('US', $result['settings']['country']);
$this->assertSame('USD', $result['settings']['currency']);
+ // TODO: Test all settings
$this->assertTrue(is_array($result['accounts']));
$this->assertTrue(is_array($result['wallets']));
@@ -460,6 +461,7 @@
'first_name' => 'John2',
'last_name' => 'Doe2',
'email' => 'john2.doe2@kolab.org',
+ 'organization' => 'TestOrg',
'aliases' => ['useralias1@kolab.org', 'useralias2@kolab.org'],
];
@@ -499,6 +501,7 @@
$this->assertInstanceOf(User::class, $user);
$this->assertSame('John2', $user->getSetting('first_name'));
$this->assertSame('Doe2', $user->getSetting('last_name'));
+ $this->assertSame('TestOrg', $user->getSetting('organization'));
$aliases = $user->aliases()->orderBy('alias')->get();
$this->assertCount(2, $aliases);
$this->assertSame('useralias1@kolab.org', $aliases[0]->alias);
@@ -575,6 +578,7 @@
'password_confirmation' => 'simple',
'first_name' => 'John2',
'last_name' => 'Doe2',
+ 'organization' => 'TestOrg',
'phone' => '+123 123 123',
'external_email' => 'external@gmail.com',
'billing_address' => 'billing',
@@ -605,6 +609,7 @@
$post = [
'first_name' => '',
'last_name' => '',
+ 'organization' => '',
'phone' => '',
'external_email' => '',
'billing_address' => '',
diff --git a/src/tests/Feature/Jobs/SignupVerificationEmailTest.php b/src/tests/Feature/Jobs/SignupVerificationEmailTest.php
--- a/src/tests/Feature/Jobs/SignupVerificationEmailTest.php
+++ b/src/tests/Feature/Jobs/SignupVerificationEmailTest.php
@@ -24,7 +24,8 @@
$this->code = SignupCode::create([
'data' => [
'email' => 'SignupVerificationEmailTest1@' . \config('app.domain'),
- 'name' => "Test Job"
+ 'first_name' => "Test",
+ 'last_name' => "Job"
]
]);
}
diff --git a/src/tests/Feature/Jobs/UserVerifyTest.php b/src/tests/Feature/Jobs/UserVerifyTest.php
--- a/src/tests/Feature/Jobs/UserVerifyTest.php
+++ b/src/tests/Feature/Jobs/UserVerifyTest.php
@@ -14,12 +14,16 @@
{
parent::setUp();
- $this->deleteTestUser('jane@kolabnow.com');
+ $ned = $this->getTestUser('ned@kolab.org');
+ $ned->status |= User::STATUS_IMAP_READY;
+ $ned->save();
}
public function tearDown(): void
{
- $this->deleteTestUser('jane@kolabnow.com');
+ $ned = $this->getTestUser('ned@kolab.org');
+ $ned->status |= User::STATUS_IMAP_READY;
+ $ned->save();
parent::tearDown();
}
@@ -33,17 +37,11 @@
{
Queue::fake();
- $user = $this->getTestUser('jane@kolabnow.com');
+ $user = $this->getTestUser('ned@kolab.org');
+ $user->status ^= User::STATUS_IMAP_READY;
+ $user->save();
- // This is a valid assertion in a feature, not functional test environment.
$this->assertFalse($user->isImapReady());
- $this->assertFalse($user->isLdapReady());
-
- $job = new UserCreate($user);
- $job->handle();
-
- $this->assertFalse($user->isImapReady());
- $this->assertTrue($user->isLdapReady());
for ($i = 0; $i < 10; $i++) {
$job = new UserVerify($user);
diff --git a/src/tests/Feature/UserTest.php b/src/tests/Feature/UserTest.php
--- a/src/tests/Feature/UserTest.php
+++ b/src/tests/Feature/UserTest.php
@@ -13,8 +13,7 @@
{
parent::setUp();
- $this->deleteTestUser('user-create-test@' . \config('app.domain'));
- $this->deleteTestUser('userdeletejob@kolabnow.com');
+ $this->deleteTestUser('user-test@' . \config('app.domain'));
$this->deleteTestUser('UserAccountA@UserAccount.com');
$this->deleteTestUser('UserAccountB@UserAccount.com');
$this->deleteTestUser('UserAccountC@UserAccount.com');
@@ -23,8 +22,7 @@
public function tearDown(): void
{
- $this->deleteTestUser('user-create-test@' . \config('app.domain'));
- $this->deleteTestUser('userdeletejob@kolabnow.com');
+ $this->deleteTestUser('user-test@' . \config('app.domain'));
$this->deleteTestUser('UserAccountA@UserAccount.com');
$this->deleteTestUser('UserAccountB@UserAccount.com');
$this->deleteTestUser('UserAccountC@UserAccount.com');
@@ -67,7 +65,7 @@
Queue::assertNothingPushed();
$user = User::create([
- 'email' => 'user-create-test@' . \config('app.domain')
+ 'email' => 'user-test@' . \config('app.domain')
]);
Queue::assertPushed(\App\Jobs\UserCreate::class, 1);
@@ -191,7 +189,7 @@
{
Queue::fake();
- $user = $this->getTestUser('userdeletejob@kolabnow.com');
+ $user = $this->getTestUser('user-test@' . \config('app.domain'));
$package = \App\Package::where('title', 'kolab')->first();
$user->assignPackage($package);
@@ -287,6 +285,29 @@
}
/**
+ * Test User::name()
+ */
+ public function testName(): void
+ {
+ Queue::fake();
+
+ $user = $this->getTestUser('user-test@' . \config('app.domain'));
+
+ $this->assertSame('', $user->name());
+ $this->assertSame(\config('app.name') . ' User', $user->name(true));
+
+ $user->setSetting('first_name', 'First');
+
+ $this->assertSame('First', $user->name());
+ $this->assertSame('First', $user->name(true));
+
+ $user->setSetting('last_name', 'Last');
+
+ $this->assertSame('First Last', $user->name());
+ $this->assertSame('First Last', $user->name(true));
+ }
+
+ /**
* Tests for UserAliasesTrait::setAliases()
*/
public function testSetAliases(): void
@@ -335,11 +356,88 @@
}
/**
- * Tests for UserSettingsTrait::setSettings()
+ * Tests for UserSettingsTrait::setSettings() and getSetting()
*/
- public function testSetSettings(): void
+ public function testUserSettings(): void
{
- $this->markTestIncomplete();
+ Queue::fake();
+ Queue::assertNothingPushed();
+
+ $user = $this->getTestUser('UserAccountA@UserAccount.com');
+
+ Queue::assertPushed(\App\Jobs\UserUpdate::class, 0);
+
+ // Test default settings
+ // Note: Technicly this tests UserObserver::created() behavior
+ $all_settings = $user->settings()->orderBy('key')->get();
+ $this->assertCount(2, $all_settings);
+ $this->assertSame('country', $all_settings[0]->key);
+ $this->assertSame('CH', $all_settings[0]->value);
+ $this->assertSame('currency', $all_settings[1]->key);
+ $this->assertSame('CHF', $all_settings[1]->value);
+
+ // Add a setting
+ $user->setSetting('first_name', 'Firstname');
+
+ Queue::assertPushed(\App\Jobs\UserUpdate::class, 1);
+
+ // Note: We test both current user as well as fresh user object
+ // to make sure cache works as expected
+ $this->assertSame('Firstname', $user->getSetting('first_name'));
+ $this->assertSame('Firstname', $user->fresh()->getSetting('first_name'));
+
+ // Update a setting
+ $user->setSetting('first_name', 'Firstname1');
+
+ Queue::assertPushed(\App\Jobs\UserUpdate::class, 2);
+
+ // Note: We test both current user as well as fresh user object
+ // to make sure cache works as expected
+ $this->assertSame('Firstname1', $user->getSetting('first_name'));
+ $this->assertSame('Firstname1', $user->fresh()->getSetting('first_name'));
+
+ // Delete a setting (null)
+ $user->setSetting('first_name', null);
+
+ Queue::assertPushed(\App\Jobs\UserUpdate::class, 3);
+
+ // Note: We test both current user as well as fresh user object
+ // to make sure cache works as expected
+ $this->assertSame(null, $user->getSetting('first_name'));
+ $this->assertSame(null, $user->fresh()->getSetting('first_name'));
+
+ // Delete a setting (empty string)
+ $user->setSetting('first_name', 'Firstname1');
+ $user->setSetting('first_name', '');
+
+ Queue::assertPushed(\App\Jobs\UserUpdate::class, 5);
+
+ // Note: We test both current user as well as fresh user object
+ // to make sure cache works as expected
+ $this->assertSame(null, $user->getSetting('first_name'));
+ $this->assertSame(null, $user->fresh()->getSetting('first_name'));
+
+ // Set multiple settings at once
+ $user->setSettings([
+ 'first_name' => 'Firstname2',
+ 'last_name' => 'Lastname2',
+ 'country' => null,
+ ]);
+
+ // TODO: This really should create a single UserUpdate job, not 3
+ Queue::assertPushed(\App\Jobs\UserUpdate::class, 7);
+
+ // Note: We test both current user as well as fresh user object
+ // to make sure cache works as expected
+ $this->assertSame('Firstname2', $user->getSetting('first_name'));
+ $this->assertSame('Firstname2', $user->fresh()->getSetting('first_name'));
+ $this->assertSame('Lastname2', $user->getSetting('last_name'));
+ $this->assertSame('Lastname2', $user->fresh()->getSetting('last_name'));
+ $this->assertSame(null, $user->getSetting('country'));
+ $this->assertSame(null, $user->fresh()->getSetting('country'));
+
+ $all_settings = $user->settings()->orderBy('key')->get();
+ $this->assertCount(3, $all_settings);
}
/**
diff --git a/src/tests/TestCase.php b/src/tests/TestCase.php
--- a/src/tests/TestCase.php
+++ b/src/tests/TestCase.php
@@ -26,5 +26,6 @@
// If we wanted to access both user and admin in one test
// we can also just call post/get/whatever with full url
\config(['app.url' => str_replace('//', '//admin.', \config('app.url'))]);
+ url()->forceRootUrl(config('app.url'));
}
}
diff --git a/src/tests/Unit/Mail/PasswordResetTest.php b/src/tests/Unit/Mail/PasswordResetTest.php
--- a/src/tests/Unit/Mail/PasswordResetTest.php
+++ b/src/tests/Unit/Mail/PasswordResetTest.php
@@ -35,6 +35,6 @@
$this->assertSame(\config('app.name') . ' Password Reset', $mail->subject);
$this->assertStringStartsWith('<!DOCTYPE html>', $html);
$this->assertTrue(strpos($html, $link) > 0);
- $this->assertTrue(strpos($html, $code->user->name) > 0);
+ $this->assertTrue(strpos($html, $code->user->name(true)) > 0);
}
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Mar 29, 10:47 PM (1 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18778263
Default Alt Text
D1213.1774824461.diff (65 KB)
Attached To
Mode
D1213: T332912: Users table cleanup
Attached
Detach File
Event Timeline