Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117778984
D1459.1775245438.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
21 KB
Referenced Files
None
Subscribers
None
D1459.1775245438.diff
View Options
diff --git a/src/app/Http/Controllers/API/AuthController.php b/src/app/Http/Controllers/API/AuthController.php
--- a/src/app/Http/Controllers/API/AuthController.php
+++ b/src/app/Http/Controllers/API/AuthController.php
@@ -20,6 +20,11 @@
$user = Auth::guard()->user();
$response = V4\UsersController::userResponse($user);
+ if (!empty(request()->input('refresh_token'))) {
+ // @phpstan-ignore-next-line
+ return $this->respondWithToken(Auth::guard()->refresh(), $response);
+ }
+
return response()->json($response);
}
@@ -34,13 +39,7 @@
// @phpstan-ignore-next-line
$token = Auth::guard()->login($user);
- return response()->json([
- 'status' => 'success',
- 'access_token' => $token,
- 'token_type' => 'bearer',
- // @phpstan-ignore-next-line
- 'expires_in' => Auth::guard()->factory()->getTTL() * 60,
- ]);
+ return self::respondWithToken($token, ['status' => 'success']);
}
/**
@@ -109,19 +108,18 @@
/**
* Get the token array structure.
*
- * @param string $token Respond with this token.
+ * @param string $token Respond with this token.
+ * @param array $response Additional response data
*
* @return \Illuminate\Http\JsonResponse
*/
- protected function respondWithToken($token)
+ protected static function respondWithToken($token, array $response = [])
{
- return response()->json(
- [
- 'access_token' => $token,
- 'token_type' => 'bearer',
- // @phpstan-ignore-next-line
- 'expires_in' => Auth::guard()->factory()->getTTL() * 60
- ]
- );
+ $response['access_token'] = $token;
+ $response['token_type'] = 'bearer';
+ // @phpstan-ignore-next-line
+ $response['expires_in'] = Auth::guard()->factory()->getTTL() * 60;
+
+ return response()->json($response);
}
}
diff --git a/src/app/Providers/Payment/Mollie.php b/src/app/Providers/Payment/Mollie.php
--- a/src/app/Providers/Payment/Mollie.php
+++ b/src/app/Providers/Payment/Mollie.php
@@ -18,7 +18,11 @@
*/
public function customerLink(Wallet $wallet): ?string
{
- $customer_id = self::mollieCustomerId($wallet);
+ $customer_id = self::mollieCustomerId($wallet, false);
+
+ if (!$customer_id) {
+ return null;
+ }
return sprintf(
'<a href="https://www.mollie.com/dashboard/customers/%s" target="_blank">%s</a>',
@@ -43,7 +47,7 @@
public function createMandate(Wallet $wallet, array $payment): ?array
{
// Register the user in Mollie, if not yet done
- $customer_id = self::mollieCustomerId($wallet);
+ $customer_id = self::mollieCustomerId($wallet, true);
$request = [
'amount' => [
@@ -155,7 +159,7 @@
}
// Register the user in Mollie, if not yet done
- $customer_id = self::mollieCustomerId($wallet);
+ $customer_id = self::mollieCustomerId($wallet, true);
// Note: Required fields: description, amount/currency, amount/value
@@ -211,7 +215,7 @@
return null;
}
- $customer_id = self::mollieCustomerId($wallet);
+ $customer_id = self::mollieCustomerId($wallet, true);
// Note: Required fields: description, amount/currency, amount/value
@@ -353,15 +357,16 @@
* Create one if does not exist yet.
*
* @param \App\Wallet $wallet The wallet
+ * @param bool $create Create the customer if does not exist yet
*
- * @return string Mollie customer identifier
+ * @return ?string Mollie customer identifier
*/
- protected static function mollieCustomerId(Wallet $wallet): string
+ protected static function mollieCustomerId(Wallet $wallet, bool $create = false): ?string
{
$customer_id = $wallet->getSetting('mollie_id');
// Register the user in Mollie
- if (empty($customer_id)) {
+ if (empty($customer_id) && $create) {
$customer = mollie()->customers()->create([
'name' => $wallet->owner->name(),
'email' => $wallet->id . '@private.' . \config('app.domain'),
diff --git a/src/app/Providers/Payment/Stripe.php b/src/app/Providers/Payment/Stripe.php
--- a/src/app/Providers/Payment/Stripe.php
+++ b/src/app/Providers/Payment/Stripe.php
@@ -29,7 +29,11 @@
*/
public function customerLink(Wallet $wallet): ?string
{
- $customer_id = self::stripeCustomerId($wallet);
+ $customer_id = self::stripeCustomerId($wallet, false);
+
+ if (!$customer_id) {
+ return null;
+ }
$location = 'https://dashboard.stripe.com';
@@ -62,7 +66,7 @@
public function createMandate(Wallet $wallet, array $payment): ?array
{
// Register the user in Stripe, if not yet done
- $customer_id = self::stripeCustomerId($wallet);
+ $customer_id = self::stripeCustomerId($wallet, true);
$request = [
'customer' => $customer_id,
@@ -173,7 +177,7 @@
}
// Register the user in Stripe, if not yet done
- $customer_id = self::stripeCustomerId($wallet);
+ $customer_id = self::stripeCustomerId($wallet, true);
$request = [
'customer' => $customer_id,
@@ -371,15 +375,16 @@
* Create one if does not exist yet.
*
* @param \App\Wallet $wallet The wallet
+ * @param bool $create Create the customer if does not exist yet
*
- * @return string Stripe customer identifier
+ * @return string|null Stripe customer identifier
*/
- protected static function stripeCustomerId(Wallet $wallet): string
+ protected static function stripeCustomerId(Wallet $wallet, bool $create = false): ?string
{
$customer_id = $wallet->getSetting('stripe_id');
// Register the user in Stripe
- if (empty($customer_id)) {
+ if (empty($customer_id) && $create) {
$customer = StripeAPI\Customer::create([
'name' => $wallet->owner->name(),
// Stripe will display the email on Checkout page, editable,
diff --git a/src/resources/js/app.js b/src/resources/js/app.js
--- a/src/resources/js/app.js
+++ b/src/resources/js/app.js
@@ -69,7 +69,6 @@
let timeout = response.expires_in || 0
// We'll refresh 60 seconds before the token expires
- // or immediately when we have no expiration time (on token re-use)
if (timeout > 60) {
timeout -= 60
}
@@ -82,7 +81,6 @@
axios.post('/api/auth/refresh').then(response => {
this.loginUser(response.data, false, true)
})
-
}, timeout * 1000)
},
// Set user state to "not logged in"
@@ -104,7 +102,7 @@
startLoading() {
this.isLoading = true
// Lock the UI with the 'loading...' element
- let loading = $('#app > .app-loader').show()
+ let loading = $('#app > .app-loader').removeClass('fadeOut')
if (!loading.length) {
$('#app').append($(loader))
}
@@ -170,7 +168,7 @@
})
},
price(price, currency) {
- return (price/100).toLocaleString('de-DE', { style: 'currency', currency: currency || 'CHF' })
+ return ((price || 0) / 100).toLocaleString('de-DE', { style: 'currency', currency: currency || 'CHF' })
},
priceLabel(cost, units = 1, discount) {
let index = ''
diff --git a/src/resources/vue/App.vue b/src/resources/vue/App.vue
--- a/src/resources/vue/App.vue
+++ b/src/resources/vue/App.vue
@@ -17,11 +17,11 @@
this.$root.startLoading()
axios.defaults.headers.common.Authorization = 'Bearer ' + token
- axios.get('/api/auth/info')
+ axios.get('/api/auth/info?refresh_token=1')
.then(response => {
this.isLoading = false
this.$root.stopLoading()
- this.$root.loginUser({ access_token: token }, false)
+ this.$root.loginUser(response.data, false)
this.$store.state.authInfo = response.data
})
.catch(error => {
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
@@ -193,10 +193,14 @@
this.discount_description = wallet.discount_description
}
+ this.$root.startLoading()
+
if (this.user_id === 'new') {
// do nothing (for now)
axios.get('/api/v4/packages')
.then(response => {
+ this.$root.stopLoading()
+
this.packages = response.data.filter(pkg => !pkg.isDomain)
this.package_id = this.packages[0].id
})
@@ -205,6 +209,8 @@
else {
axios.get('/api/v4/users/' + this.user_id)
.then(response => {
+ this.$root.stopLoading()
+
this.user = response.data
this.user.first_name = response.data.settings.first_name
this.user.last_name = response.data.settings.last_name
diff --git a/src/tests/Browser/Admin/DashboardTest.php b/src/tests/Browser/Admin/DashboardTest.php
--- a/src/tests/Browser/Admin/DashboardTest.php
+++ b/src/tests/Browser/Admin/DashboardTest.php
@@ -70,8 +70,10 @@
->click('@search form button')
->assertMissing('@search table')
->waitForLocation('/user/' . $john->id)
- ->waitFor('#user-info')
- ->assertSeeIn('#user-info .card-title', $john->email);
+ ->waitUntilMissing('.app-loader')
+ ->whenAvailable('#user-info', function (Browser $browser) use ($john) {
+ $browser->assertSeeIn('.card-title', $john->email);
+ });
});
}
}
diff --git a/src/tests/Browser/Admin/UserFinancesTest.php b/src/tests/Browser/Admin/UserFinancesTest.php
--- a/src/tests/Browser/Admin/UserFinancesTest.php
+++ b/src/tests/Browser/Admin/UserFinancesTest.php
@@ -30,6 +30,7 @@
$wallet->discount()->dissociate();
$wallet->balance = 0;
$wallet->save();
+ $wallet->setSettings(['mollie_id' => null, 'stripe_id' => null]);
}
/**
@@ -40,7 +41,9 @@
// Assert Jack's Finances tab
$this->browse(function (Browser $browser) {
$jack = $this->getTestUser('jack@kolab.org');
- $jack->wallets()->first()->transactions()->delete();
+ $wallet = $jack->wallets()->first();
+ $wallet->transactions()->delete();
+ $wallet->setSetting('stripe_id', 'abc');
$page = new UserPage($jack->id);
$browser->visit(new Home())
@@ -54,12 +57,11 @@
->assertSeeIn('.card-title:first-child', 'Account balance')
->assertSeeIn('.card-title:first-child .text-success', '0,00 CHF')
->with('form', function (Browser $browser) {
- $payment_provider = ucfirst(\config('services.payment_provider'));
$browser->assertElementsCount('.row', 2)
->assertSeeIn('.row:nth-child(1) label', 'Discount')
->assertSeeIn('.row:nth-child(1) #discount span', 'none')
- ->assertSeeIn('.row:nth-child(2) label', $payment_provider . ' ID')
- ->assertVisible('.row:nth-child(2) a');
+ ->assertSeeIn('.row:nth-child(2) label', 'Stripe ID')
+ ->assertSeeIn('.row:nth-child(2) a', 'abc');
})
->assertSeeIn('h2:nth-of-type(2)', 'Transactions')
->with('table', function (Browser $browser) {
@@ -101,7 +103,7 @@
->assertSeeIn('.card-title:first-child', 'Account balance')
->assertSeeIn('.card-title:first-child .text-danger', '-20,10 CHF')
->with('form', function (Browser $browser) {
- $browser->assertElementsCount('.row', 2)
+ $browser->assertElementsCount('.row', 1)
->assertSeeIn('.row:nth-child(1) label', 'Discount')
->assertSeeIn('.row:nth-child(1) #discount span', '10% - Test voucher');
})
@@ -127,7 +129,7 @@
->assertSeeIn('.card-title:first-child', 'Account balance')
->assertSeeIn('.card-title:first-child .text-success', '0,00 CHF')
->with('form', function (Browser $browser) {
- $browser->assertElementsCount('.row', 2)
+ $browser->assertElementsCount('.row', 1)
->assertSeeIn('.row:nth-child(1) label', 'Discount')
->assertSeeIn('.row:nth-child(1) #discount span', 'none');
})
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
@@ -33,6 +33,7 @@
}
$wallet = $john->wallets()->first();
$wallet->discount()->dissociate();
+ $wallet->save();
}
/**
@@ -50,6 +51,7 @@
}
$wallet = $john->wallets()->first();
$wallet->discount()->dissociate();
+ $wallet->save();
parent::tearDown();
}
diff --git a/src/tests/Browser/DomainTest.php b/src/tests/Browser/DomainTest.php
--- a/src/tests/Browser/DomainTest.php
+++ b/src/tests/Browser/DomainTest.php
@@ -118,6 +118,7 @@
->click('@links a.link-domains')
// On Domains List page click the domain entry
->on(new DomainList())
+ ->waitFor('@table tbody tr')
->assertVisible('@table tbody tr:first-child td:first-child svg.fa-globe.text-success')
->assertText('@table tbody tr:first-child td:first-child svg title', 'Active')
->assertSeeIn('@table tbody tr:first-child td:first-child', 'kolab.org')
diff --git a/src/tests/Browser/Pages/PaymentStripe.php b/src/tests/Browser/Pages/PaymentStripe.php
--- a/src/tests/Browser/Pages/PaymentStripe.php
+++ b/src/tests/Browser/Pages/PaymentStripe.php
@@ -37,8 +37,8 @@
{
return [
'@form' => '.App-Payment > form',
- '@title' => '.App-Overview .ProductSummary-Info .Text',
- '@amount' => '#ProductSummary-TotalAmount',
+ '@title' => '.App-Overview .ProductSummary',
+ '@amount' => '#ProductSummary-totalAmount',
'@description' => '#ProductSummary-Description',
'@email-input' => '.App-Payment #email',
'@cardnumber-input' => '.App-Payment #cardNumber',
diff --git a/src/tests/Browser/Pages/UserInfo.php b/src/tests/Browser/Pages/UserInfo.php
--- a/src/tests/Browser/Pages/UserInfo.php
+++ b/src/tests/Browser/Pages/UserInfo.php
@@ -25,7 +25,8 @@
*/
public function assert($browser)
{
- $browser->waitFor('@form');
+ $browser->waitFor('@form')
+ ->waitUntilMissing('.app-loader');
}
/**
diff --git a/src/tests/Browser/PasswordResetTest.php b/src/tests/Browser/PasswordResetTest.php
--- a/src/tests/Browser/PasswordResetTest.php
+++ b/src/tests/Browser/PasswordResetTest.php
@@ -146,9 +146,10 @@
$browser->waitFor('.toast-error');
- $step->assertVisible('#reset_short_code.is-invalid');
- $step->assertVisible('#reset_short_code + .invalid-feedback');
- $step->assertFocused('#reset_short_code');
+ $step->waitFor('#reset_short_code.is-invalid')
+ ->assertVisible('#reset_short_code.is-invalid')
+ ->assertVisible('#reset_short_code + .invalid-feedback')
+ ->assertFocused('#reset_short_code');
$browser->click('.toast-error'); // remove the toast
});
@@ -249,9 +250,10 @@
$browser->waitFor('.toast-error');
- $step->assertVisible('#reset_password.is-invalid');
- $step->assertVisible('#reset_password + .invalid-feedback');
- $step->assertFocused('#reset_password');
+ $step->waitFor('#reset_password.is-invalid')
+ ->assertVisible('#reset_password.is-invalid')
+ ->assertVisible('#reset_password + .invalid-feedback')
+ ->assertFocused('#reset_password');
$browser->click('.toast-error'); // remove the toast
});
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
@@ -482,6 +482,7 @@
$this->browse(function (Browser $browser) {
$browser->visit('/signup/voucher/TEST')
->onWithoutAssert(new Signup())
+ ->waitUntilMissing('.app-loader')
->waitFor('@step0')
->click('.plan-individual button')
->whenAvailable('@step1', function (Browser $browser) {
diff --git a/src/tests/Browser/StatusTest.php b/src/tests/Browser/StatusTest.php
--- a/src/tests/Browser/StatusTest.php
+++ b/src/tests/Browser/StatusTest.php
@@ -158,6 +158,7 @@
$browser->on(new Dashboard())
->click('@links a.link-domains')
->on(new DomainList())
+ ->waitFor('@table tbody tr')
// Assert domain status icon
->assertVisible('@table tbody tr:first-child td:first-child svg.fa-globe.text-danger')
->assertText('@table tbody tr:first-child td:first-child svg title', 'Not Ready')
@@ -222,6 +223,7 @@
$browser->visit(new Dashboard())
->click('@links a.link-users')
->on(new UserList())
+ ->waitFor('@table tbody tr')
// Assert user status icons
->assertVisible('@table tbody tr:first-child td:first-child svg.fa-user.text-success')
->assertText('@table tbody tr:first-child td:first-child svg title', 'Active')
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
@@ -107,7 +107,8 @@
->click('@links .link-users')
->on(new UserList())
->whenAvailable('@table', function (Browser $browser) {
- $browser->assertElementsCount('tbody tr', 4)
+ $browser->waitFor('tbody tr')
+ ->assertElementsCount('tbody tr', 4)
->assertSeeIn('tbody tr:nth-child(1) a', 'jack@kolab.org')
->assertSeeIn('tbody tr:nth-child(2) a', 'joe@kolab.org')
->assertSeeIn('tbody tr:nth-child(3) a', 'john@kolab.org')
@@ -516,6 +517,7 @@
->on(new Home())
->submitLogon('john@kolab.org', 'simple123', true)
->visit(new UserList())
+ ->waitFor('@table tr:nth-child(2)')
->click('@table tr:nth-child(2) a')
->on(new UserInfo())
->with('@form', function (Browser $browser) {
diff --git a/src/tests/Feature/Controller/Admin/WalletsTest.php b/src/tests/Feature/Controller/Admin/WalletsTest.php
--- a/src/tests/Feature/Controller/Admin/WalletsTest.php
+++ b/src/tests/Feature/Controller/Admin/WalletsTest.php
@@ -63,7 +63,7 @@
$this->assertTrue(empty($json['description']));
$this->assertTrue(empty($json['discount_description']));
$this->assertTrue(!empty($json['provider']));
- $this->assertTrue(!empty($json['providerLink']));
+ $this->assertTrue(empty($json['providerLink']));
$this->assertTrue(!empty($json['mandate']));
}
diff --git a/src/tests/Feature/Controller/AuthTest.php b/src/tests/Feature/Controller/AuthTest.php
--- a/src/tests/Feature/Controller/AuthTest.php
+++ b/src/tests/Feature/Controller/AuthTest.php
@@ -52,8 +52,27 @@
$this->assertTrue(is_array($json['statusInfo']));
$this->assertTrue(is_array($json['settings']));
$this->assertTrue(is_array($json['aliases']));
+ $this->assertTrue(!isset($json['access_token']));
// Note: Details of the content are tested in testUserResponse()
+
+ // Test token refresh via the info request
+ // First we log in as we need the token (actingAs() will not work)
+ $post = ['email' => 'john@kolab.org', 'password' => 'simple123'];
+ $response = $this->post("api/auth/login", $post);
+ $json = $response->json();
+ $response = $this->withHeaders(['Authorization' => 'Bearer ' . $json['access_token']])
+ ->get("api/auth/info?refresh_token=1");
+ $response->assertStatus(200);
+
+ $json = $response->json();
+
+ $this->assertEquals('john@kolab.org', $json['email']);
+ $this->assertTrue(is_array($json['statusInfo']));
+ $this->assertTrue(is_array($json['settings']));
+ $this->assertTrue(is_array($json['aliases']));
+ $this->assertTrue(!empty($json['access_token']));
+ $this->assertTrue(!empty($json['expires_in']));
}
/**
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Apr 3, 7:43 PM (8 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18821683
Default Alt Text
D1459.1775245438.diff (21 KB)
Attached To
Mode
D1459: Don't create Mollie/Stripe ID until user makes a payment
Attached
Detach File
Event Timeline