mirror of
https://github.com/crater-invoice/crater.git
synced 2025-10-27 11:41:09 -04:00
Add Domain Verification on Onboarding Wizard
This commit is contained in:
@ -3,8 +3,12 @@
|
|||||||
namespace Crater\Http\Controllers\V1\Mobile;
|
namespace Crater\Http\Controllers\V1\Mobile;
|
||||||
|
|
||||||
use Crater\Http\Controllers\Controller;
|
use Crater\Http\Controllers\Controller;
|
||||||
|
use Crater\Http\Requests\DomainEnvironmentRequest;
|
||||||
use Crater\Models\User;
|
use Crater\Models\User;
|
||||||
|
use Crater\Space\EnvironmentManager;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Artisan;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
@ -40,4 +44,9 @@ class AuthController extends Controller
|
|||||||
'success' => true,
|
'success' => true,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function check()
|
||||||
|
{
|
||||||
|
return Auth::check();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
33
app/Http/Controllers/V1/Onboarding/AppDomainController.php
Normal file
33
app/Http/Controllers/V1/Onboarding/AppDomainController.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Crater\Http\Controllers\V1\Onboarding;
|
||||||
|
|
||||||
|
use Crater\Http\Controllers\Controller;
|
||||||
|
use Crater\Http\Requests\DomainEnvironmentRequest;
|
||||||
|
use Crater\Space\EnvironmentManager;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Artisan;
|
||||||
|
|
||||||
|
class AppDomainController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param DomainEnvironmentRequest $request
|
||||||
|
*/
|
||||||
|
public function __invoke(DomainEnvironmentRequest $request)
|
||||||
|
{
|
||||||
|
Artisan::call('optimize:clear');
|
||||||
|
|
||||||
|
$environmentManager = new EnvironmentManager();
|
||||||
|
|
||||||
|
$results = $environmentManager->saveDomainVariables($request);
|
||||||
|
|
||||||
|
if (in_array('error', $results)) {
|
||||||
|
return response()->json($results);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'success' => false,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -32,16 +32,20 @@ class DatabaseConfigurationController extends Controller
|
|||||||
Artisan::call('config:clear');
|
Artisan::call('config:clear');
|
||||||
Artisan::call('cache:clear');
|
Artisan::call('cache:clear');
|
||||||
|
|
||||||
|
$status = pcntl_fork();
|
||||||
|
pcntl_wait($status);
|
||||||
|
|
||||||
$results = $this->environmentManager->saveDatabaseVariables($request);
|
$results = $this->environmentManager->saveDatabaseVariables($request);
|
||||||
|
|
||||||
if (array_key_exists("success", $results)) {
|
if (array_key_exists("success", $results)) {
|
||||||
Artisan::call('key:generate --force');
|
Artisan::call('optimize:clear');
|
||||||
Artisan::call('config:clear');
|
Artisan::call('config:clear');
|
||||||
Artisan::call('cache:clear');
|
Artisan::call('cache:clear');
|
||||||
Artisan::call('storage:link');
|
Artisan::call('storage:link');
|
||||||
Artisan::call('migrate --seed --force');
|
Artisan::call('migrate --seed --force');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return response()->json($results);
|
return response()->json($results);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,6 @@ class FinishController extends Controller
|
|||||||
{
|
{
|
||||||
\Storage::disk('local')->put('database_created', 'database_created');
|
\Storage::disk('local')->put('database_created', 'database_created');
|
||||||
|
|
||||||
$user = User::where('role', 'super admin')->first();
|
return response()->json(['success' => true]);
|
||||||
Auth::login($user);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
25
app/Http/Controllers/V1/Onboarding/LoginController.php
Normal file
25
app/Http/Controllers/V1/Onboarding/LoginController.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Crater\Http\Controllers\V1\Onboarding;
|
||||||
|
|
||||||
|
use Auth;
|
||||||
|
use Crater\Http\Controllers\Controller;
|
||||||
|
use Crater\Models\User;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class LoginController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Handle the incoming request.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Http\Response
|
||||||
|
*/
|
||||||
|
public function __invoke(Request $request)
|
||||||
|
{
|
||||||
|
$user = User::where('role', 'super admin')->first();
|
||||||
|
Auth::login($user);
|
||||||
|
|
||||||
|
return response()->json(['success' => true]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -30,9 +30,6 @@ class DatabaseEnvironmentRequest extends FormRequest
|
|||||||
'required',
|
'required',
|
||||||
'url',
|
'url',
|
||||||
],
|
],
|
||||||
'app_domain' => [
|
|
||||||
'required',
|
|
||||||
],
|
|
||||||
'database_connection' => [
|
'database_connection' => [
|
||||||
'required',
|
'required',
|
||||||
'string',
|
'string',
|
||||||
@ -50,9 +47,6 @@ class DatabaseEnvironmentRequest extends FormRequest
|
|||||||
'required',
|
'required',
|
||||||
'url',
|
'url',
|
||||||
],
|
],
|
||||||
'app_domain' => [
|
|
||||||
'required',
|
|
||||||
],
|
|
||||||
'database_connection' => [
|
'database_connection' => [
|
||||||
'required',
|
'required',
|
||||||
'string',
|
'string',
|
||||||
|
|||||||
32
app/Http/Requests/DomainEnvironmentRequest.php
Normal file
32
app/Http/Requests/DomainEnvironmentRequest.php
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Crater\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class DomainEnvironmentRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'app_domain' => [
|
||||||
|
'required',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -262,6 +262,11 @@ class User extends Authenticatable implements HasMedia
|
|||||||
$query->orWhere('users.id', $customer_id);
|
$query->orWhere('users.id', $customer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function scopeWhereSuperAdmin($query)
|
||||||
|
{
|
||||||
|
$query->orWhere('role', 'super admin');
|
||||||
|
}
|
||||||
|
|
||||||
public function scopeApplyInvoiceFilters($query, array $filters)
|
public function scopeApplyInvoiceFilters($query, array $filters)
|
||||||
{
|
{
|
||||||
$filters = collect($filters);
|
$filters = collect($filters);
|
||||||
|
|||||||
@ -4,6 +4,7 @@ namespace Crater\Space;
|
|||||||
|
|
||||||
use Crater\Http\Requests\DatabaseEnvironmentRequest;
|
use Crater\Http\Requests\DatabaseEnvironmentRequest;
|
||||||
use Crater\Http\Requests\DiskEnvironmentRequest;
|
use Crater\Http\Requests\DiskEnvironmentRequest;
|
||||||
|
use Crater\Http\Requests\DomainEnvironmentRequest;
|
||||||
use Crater\Http\Requests\MailEnvironmentRequest;
|
use Crater\Http\Requests\MailEnvironmentRequest;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@ -359,11 +360,11 @@ class EnvironmentManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save the disk content to the .env file.
|
* Save the disk content to the .env file.
|
||||||
*
|
*
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function saveDiskVariables(DiskEnvironmentRequest $request)
|
public function saveDiskVariables(DiskEnvironmentRequest $request)
|
||||||
{
|
{
|
||||||
$diskData = $this->getDiskData($request);
|
$diskData = $this->getDiskData($request);
|
||||||
@ -486,4 +487,35 @@ class EnvironmentManager
|
|||||||
'old_default_driver' => $oldDefaultDriver,
|
'old_default_driver' => $oldDefaultDriver,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save sanctum statful domain to the .env file.
|
||||||
|
*
|
||||||
|
* @param DomainEnvironmentRequest $request
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function saveDomainVariables(DomainEnvironmentRequest $request)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
file_put_contents($this->envPath, str_replace(
|
||||||
|
'SANCTUM_STATEFUL_DOMAINS='.env('SANCTUM_STATEFUL_DOMAINS'),
|
||||||
|
'SANCTUM_STATEFUL_DOMAINS='.$request->app_domain,
|
||||||
|
file_get_contents($this->envPath)
|
||||||
|
));
|
||||||
|
|
||||||
|
file_put_contents($this->envPath, str_replace(
|
||||||
|
'SESSION_DOMAIN='.config('session.domain'),
|
||||||
|
'SESSION_DOMAIN='.explode(':', $request->app_domain)[0],
|
||||||
|
file_get_contents($this->envPath)
|
||||||
|
));
|
||||||
|
} catch (Exception $e) {
|
||||||
|
return [
|
||||||
|
'error' => 'domain_verification_failed'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'success' => 'domain_variable_save_successfully'
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
resources/assets/js/bootstrap.js
vendored
2
resources/assets/js/bootstrap.js
vendored
@ -126,9 +126,11 @@ global.axios.interceptors.response.use(undefined, function (err) {
|
|||||||
} else {
|
} else {
|
||||||
if (
|
if (
|
||||||
err.response.data &&
|
err.response.data &&
|
||||||
|
err.config.url !== '/api/v1/auth/check' &&
|
||||||
(err.response.statusText === 'Unauthorized' ||
|
(err.response.statusText === 'Unauthorized' ||
|
||||||
err.response.data === ' Unauthorized.')
|
err.response.data === ' Unauthorized.')
|
||||||
) {
|
) {
|
||||||
|
console.log(err.response)
|
||||||
// Unauthorized and log out
|
// Unauthorized and log out
|
||||||
store.dispatch('notification/showNotification', {
|
store.dispatch('notification/showNotification', {
|
||||||
type: 'error',
|
type: 'error',
|
||||||
|
|||||||
@ -19,7 +19,7 @@ export default {
|
|||||||
stepHeadingContainer: 'heading-section',
|
stepHeadingContainer: 'heading-section',
|
||||||
stepTitle: 'text-2xl not-italic font-semibold leading-7 text-black',
|
stepTitle: 'text-2xl not-italic font-semibold leading-7 text-black',
|
||||||
stepDescription:
|
stepDescription:
|
||||||
'w-full mt-2.5 mb-8 text-sm not-italic leading-snug text-gray-500 lg:w-7/12 md:w-7/12 sm:w-7/12',
|
'w-full mt-2.5 mb-8 text-sm not-italic text-gray-600 lg:w-7/12 md:w-7/12 sm:w-7/12',
|
||||||
},
|
},
|
||||||
variants: {},
|
variants: {},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import i18n from '../plugins/i18n';
|
import i18n from '../plugins/i18n'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
addClass(el, className) {
|
addClass(el, className) {
|
||||||
@ -51,9 +51,9 @@ export default {
|
|||||||
.replace(/(\d{3})(?=\d)/g, '$1' + thousand_separator)
|
.replace(/(\d{3})(?=\d)/g, '$1' + thousand_separator)
|
||||||
let precisionText = precision
|
let precisionText = precision
|
||||||
? decimal_separator +
|
? decimal_separator +
|
||||||
Math.abs(amount - i)
|
Math.abs(amount - i)
|
||||||
.toFixed(precision)
|
.toFixed(precision)
|
||||||
.slice(2)
|
.slice(2)
|
||||||
: ''
|
: ''
|
||||||
let combinedAmountText =
|
let combinedAmountText =
|
||||||
negativeSign + thousandText + amountText + precisionText
|
negativeSign + thousandText + amountText + precisionText
|
||||||
@ -104,9 +104,9 @@ export default {
|
|||||||
.replace(/(\d{3})(?=\d)/g, '$1' + thousand_separator)
|
.replace(/(\d{3})(?=\d)/g, '$1' + thousand_separator)
|
||||||
let precisionText = precision
|
let precisionText = precision
|
||||||
? decimal_separator +
|
? decimal_separator +
|
||||||
Math.abs(amount - i)
|
Math.abs(amount - i)
|
||||||
.toFixed(precision)
|
.toFixed(precision)
|
||||||
.slice(2)
|
.slice(2)
|
||||||
: ''
|
: ''
|
||||||
let combinedAmountText =
|
let combinedAmountText =
|
||||||
negativeSign + thousandText + amountText + precisionText
|
negativeSign + thousandText + amountText + precisionText
|
||||||
@ -130,11 +130,11 @@ export default {
|
|||||||
}
|
}
|
||||||
let pattern = new RegExp(
|
let pattern = new RegExp(
|
||||||
'^(https?:\\/\\/)?' + // protocol
|
'^(https?:\\/\\/)?' + // protocol
|
||||||
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
|
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
|
||||||
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
|
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
|
||||||
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
|
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
|
||||||
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
|
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
|
||||||
'(\\#[-a-z\\d_]*)?$',
|
'(\\#[-a-z\\d_]*)?$',
|
||||||
'i'
|
'i'
|
||||||
) // fragment locator
|
) // fragment locator
|
||||||
|
|
||||||
@ -142,12 +142,20 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
checkValidDomainUrl(url) {
|
checkValidDomainUrl(url) {
|
||||||
if (url.includes('localhost')) {
|
if (url.includes('localhost') || url.includes('127.0.0.1')) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
let pattern = new RegExp(
|
let pattern = new RegExp(
|
||||||
'^([0-9A-Za-z-\\.@:%_+~#=]+)+((\\.[a-zA-Z]{2,3})+)(/(.)*)?(\\?(.)*)?'
|
'^(https?:\\/\\/)?' + // protocol
|
||||||
)
|
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
|
||||||
|
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
|
||||||
|
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
|
||||||
|
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
|
||||||
|
'(\\#[-a-z\\d_]*)?$',
|
||||||
|
'i'
|
||||||
|
) // fragment locator
|
||||||
|
|
||||||
return !!pattern.test(url)
|
return !!pattern.test(url)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -21,7 +21,6 @@ import SiteSidebar from './partials/TheSiteSidebar.vue'
|
|||||||
import BaseModal from '../../components/base/modal/BaseModal'
|
import BaseModal from '../../components/base/modal/BaseModal'
|
||||||
import { RefreshIcon } from '@vue-hero-icons/solid'
|
import { RefreshIcon } from '@vue-hero-icons/solid'
|
||||||
import { mapActions, mapGetters } from 'vuex'
|
import { mapActions, mapGetters } from 'vuex'
|
||||||
import BaseNotification from '../../components/base/BaseNotification.vue'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -30,7 +29,6 @@ export default {
|
|||||||
SiteFooter,
|
SiteFooter,
|
||||||
BaseModal,
|
BaseModal,
|
||||||
RefreshIcon,
|
RefreshIcon,
|
||||||
BaseNotification,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="site-wrapper h-full text-base">
|
<div class="h-full text-base site-wrapper">
|
||||||
|
<base-notification />
|
||||||
<div class="container mx-auto">
|
<div class="container mx-auto">
|
||||||
<router-view></router-view>
|
<router-view></router-view>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="flex flex-col items-center justify-between w-full h-32 pt-10 step-indicator"
|
class="flex flex-col items-center justify-between w-full h-32 pt-10 step-indicator"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
id="logo-crater"
|
id="logo-crater"
|
||||||
@ -22,6 +22,7 @@
|
|||||||
import SystemRequirement from './WizardSystemRequirementStep'
|
import SystemRequirement from './WizardSystemRequirementStep'
|
||||||
import Permission from './WizardPermissionStep'
|
import Permission from './WizardPermissionStep'
|
||||||
import Database from './WizardDatabaseStep'
|
import Database from './WizardDatabaseStep'
|
||||||
|
import VerifyDomain from './WizardVerifyDomainStep'
|
||||||
import EmailConfiguration from './WizardEmailConfigStep'
|
import EmailConfiguration from './WizardEmailConfigStep'
|
||||||
import UserProfile from './WizardUserProfileStep'
|
import UserProfile from './WizardUserProfileStep'
|
||||||
import CompanyInfo from './WizardCompanyInfoStep'
|
import CompanyInfo from './WizardCompanyInfoStep'
|
||||||
@ -32,10 +33,11 @@ export default {
|
|||||||
step_1: SystemRequirement,
|
step_1: SystemRequirement,
|
||||||
step_2: Permission,
|
step_2: Permission,
|
||||||
step_3: Database,
|
step_3: Database,
|
||||||
step_4: EmailConfiguration,
|
step_4: VerifyDomain,
|
||||||
step_5: UserProfile,
|
step_5: EmailConfiguration,
|
||||||
step_6: CompanyInfo,
|
step_6: UserProfile,
|
||||||
step_7: Settings,
|
step_7: CompanyInfo,
|
||||||
|
step_8: Settings,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -69,16 +71,27 @@ export default {
|
|||||||
let status = {
|
let status = {
|
||||||
profile_complete: data,
|
profile_complete: data,
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
let response = await axios.post('/api/v1/onboarding/wizard-step', status)
|
let response = await axios.post(
|
||||||
|
'/api/v1/onboarding/wizard-step',
|
||||||
|
status
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
} catch (e) {
|
||||||
|
if (e?.response?.data?.message === 'The MAC is invalid.') {
|
||||||
|
window.location.reload()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async setTab(data) {
|
async setTab(data) {
|
||||||
if (data) {
|
if (data) {
|
||||||
this.setProfileComplete(data)
|
let res = await this.setProfileComplete(data)
|
||||||
|
if (!res) return false
|
||||||
}
|
}
|
||||||
this.step++
|
this.step++
|
||||||
|
|
||||||
if (this.step <= 7) {
|
if (this.step <= 8) {
|
||||||
this.tab = 'step_' + this.step
|
this.tab = 'step_' + this.step
|
||||||
} else {
|
} else {
|
||||||
// window.location.reload()
|
// window.location.reload()
|
||||||
|
|||||||
@ -297,7 +297,7 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$emit('next', 6)
|
this.$emit('next', 7)
|
||||||
this.isLoading = false
|
this.isLoading = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -16,7 +16,6 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { validationMixin } from 'vuelidate'
|
|
||||||
import Mysql from './database/MysqlDatabase'
|
import Mysql from './database/MysqlDatabase'
|
||||||
import Pgsql from './database/PgsqlDatabase'
|
import Pgsql from './database/PgsqlDatabase'
|
||||||
import Sqlite from './database/SqliteDatabase'
|
import Sqlite from './database/SqliteDatabase'
|
||||||
@ -67,15 +66,11 @@ export default {
|
|||||||
async next(databaseData) {
|
async next(databaseData) {
|
||||||
this.isLoading = this.isFetching = true
|
this.isLoading = this.isFetching = true
|
||||||
try {
|
try {
|
||||||
await window.axios.get('/sanctum/csrf-cookie')
|
|
||||||
|
|
||||||
let response = await window.axios.post(
|
let response = await window.axios.post(
|
||||||
'/api/v1/onboarding/database/config',
|
'/api/v1/onboarding/database/config',
|
||||||
databaseData
|
databaseData
|
||||||
)
|
)
|
||||||
|
|
||||||
await window.axios.get('/sanctum/csrf-cookie')
|
|
||||||
|
|
||||||
if (response.data.success) {
|
if (response.data.success) {
|
||||||
await window.axios.post('/api/v1/onboarding/finish')
|
await window.axios.post('/api/v1/onboarding/finish')
|
||||||
|
|
||||||
|
|||||||
@ -67,7 +67,7 @@ export default {
|
|||||||
mailConfigData
|
mailConfigData
|
||||||
)
|
)
|
||||||
if (response.data.success) {
|
if (response.data.success) {
|
||||||
this.$emit('next', 4)
|
this.$emit('next', 5)
|
||||||
this.showNotification({
|
this.showNotification({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
message: this.$t('wizard.success.' + response.data.success),
|
message: this.$t('wizard.success.' + response.data.success),
|
||||||
|
|||||||
@ -246,7 +246,7 @@ export default {
|
|||||||
|
|
||||||
this.uploadAvatar(avatarData)
|
this.uploadAvatar(avatarData)
|
||||||
}
|
}
|
||||||
this.$emit('next', 5)
|
this.$emit('next', 6)
|
||||||
this.isLoading = false
|
this.isLoading = false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|||||||
136
resources/assets/js/views/wizard/WizardVerifyDomainStep.vue
Normal file
136
resources/assets/js/views/wizard/WizardVerifyDomainStep.vue
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
<template>
|
||||||
|
<sw-wizard-step
|
||||||
|
:title="$t('wizard.verify_domain.title')"
|
||||||
|
:description="$t('wizard.verify_domain.desc')"
|
||||||
|
>
|
||||||
|
<div class="w-full md:w-2/3">
|
||||||
|
<sw-input-group
|
||||||
|
:label="$t('wizard.verify_domain.app_domain')"
|
||||||
|
:error="domainError"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<sw-input
|
||||||
|
:invalid="$v.formData.app_domain.$error"
|
||||||
|
v-model.trim="formData.app_domain"
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
|
placeholder="crater.com"
|
||||||
|
@input="$v.formData.app_domain.$touch()"
|
||||||
|
/>
|
||||||
|
</sw-input-group>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="mt-4 mb-0 text-sm text-gray-600">Notes:</p>
|
||||||
|
<ul class="w-full text-gray-600 list-disc list-inside">
|
||||||
|
<li class="text-sm leading-8">
|
||||||
|
App domain should not contain
|
||||||
|
<b class="inline-block px-1 bg-gray-100 rounded-sm">https://</b> or
|
||||||
|
<b class="inline-block px-1 bg-gray-100 rounded-sm">http</b> in front of
|
||||||
|
the domain.
|
||||||
|
</li>
|
||||||
|
<li class="text-sm leading-8">
|
||||||
|
If you're accessing the website on a different port, please mention the
|
||||||
|
port. For example:
|
||||||
|
<b class="inline-block px-1 bg-gray-100">localhost:8080</b>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<sw-button
|
||||||
|
:loading="isLoading"
|
||||||
|
:disabled="isLoading"
|
||||||
|
class="mt-8"
|
||||||
|
variant="primary"
|
||||||
|
@click="verifyDomain"
|
||||||
|
>
|
||||||
|
{{ $t('wizard.verify_domain.verify_now') }}
|
||||||
|
</sw-button>
|
||||||
|
</sw-wizard-step>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { ArrowRightIcon } from '@vue-hero-icons/solid'
|
||||||
|
const { required } = require('vuelidate/lib/validators')
|
||||||
|
import { mapActions } from 'vuex'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
ArrowRightIcon,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
formData: {
|
||||||
|
app_domain: window.location.origin.replace(/(^\w+:|^)\/\//, ''),
|
||||||
|
},
|
||||||
|
isLoading: false,
|
||||||
|
isShow: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
validations: {
|
||||||
|
formData: {
|
||||||
|
app_domain: {
|
||||||
|
required,
|
||||||
|
isUrl(val) {
|
||||||
|
return this.$utils.checkValidDomainUrl(val)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
hasNext() {
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
domainError() {
|
||||||
|
if (!this.$v.formData.app_domain.$error) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.$v.formData.app_domain.required) {
|
||||||
|
return this.$tc('validation.required')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.$v.formData.app_domain.isUrl) {
|
||||||
|
return this.$tc('validation.invalid_domain_url')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
...mapActions('notification', ['showNotification']),
|
||||||
|
listToggle() {
|
||||||
|
this.isShow = !this.isShow
|
||||||
|
},
|
||||||
|
|
||||||
|
async verifyDomain() {
|
||||||
|
this.$v.formData.$touch()
|
||||||
|
|
||||||
|
if (this.$v.formData.$invalid) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isLoading = true
|
||||||
|
try {
|
||||||
|
await window.axios.put('api/v1/onboarding/set-domain', this.formData)
|
||||||
|
|
||||||
|
await window.axios.get('/sanctum/csrf-cookie')
|
||||||
|
|
||||||
|
await window.axios.post('/api/v1/onboarding/login')
|
||||||
|
|
||||||
|
let driverRes = await window.axios.get('/api/v1/auth/check')
|
||||||
|
|
||||||
|
if (driverRes.data) {
|
||||||
|
await this.$emit('next', 4)
|
||||||
|
}
|
||||||
|
this.isLoading = false
|
||||||
|
} catch (e) {
|
||||||
|
this.showNotification({
|
||||||
|
type: 'error',
|
||||||
|
message: this.$t('wizard.errors.domain_verification_failed'),
|
||||||
|
})
|
||||||
|
this.isLoading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<form action="" @submit.prevent="next()">
|
<form action="" @submit.prevent="next()">
|
||||||
<div>
|
<div>
|
||||||
<div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6">
|
<div class="grid grid-cols-1 gap-5 md:grid-cols-2 lg:mb-6 md:mb-6">
|
||||||
<sw-input-group
|
<sw-input-group
|
||||||
:label="$t('wizard.database.app_url')"
|
:label="$t('wizard.database.app_url')"
|
||||||
:error="urlError"
|
:error="urlError"
|
||||||
@ -16,23 +16,6 @@
|
|||||||
/>
|
/>
|
||||||
</sw-input-group>
|
</sw-input-group>
|
||||||
|
|
||||||
<sw-input-group
|
|
||||||
:label="$t('wizard.database.app_domain')"
|
|
||||||
:error="domainError"
|
|
||||||
required
|
|
||||||
>
|
|
||||||
<sw-input
|
|
||||||
:invalid="$v.databaseData.app_domain.$error"
|
|
||||||
v-model.trim="databaseData.app_domain"
|
|
||||||
type="text"
|
|
||||||
name="name"
|
|
||||||
placeholder="crater.com"
|
|
||||||
@input="$v.databaseData.app_domain.$touch()"
|
|
||||||
/>
|
|
||||||
</sw-input-group>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6">
|
|
||||||
<sw-input-group
|
<sw-input-group
|
||||||
:label="$t('wizard.database.connection')"
|
:label="$t('wizard.database.connection')"
|
||||||
:error="connectionError"
|
:error="connectionError"
|
||||||
@ -62,9 +45,7 @@
|
|||||||
@input="$v.databaseData.database_port.$touch()"
|
@input="$v.databaseData.database_port.$touch()"
|
||||||
/>
|
/>
|
||||||
</sw-input-group>
|
</sw-input-group>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6">
|
|
||||||
<sw-input-group
|
<sw-input-group
|
||||||
:label="$t('wizard.database.db_name')"
|
:label="$t('wizard.database.db_name')"
|
||||||
:error="nameError"
|
:error="nameError"
|
||||||
@ -92,9 +73,7 @@
|
|||||||
@input="$v.databaseData.database_username.$touch()"
|
@input="$v.databaseData.database_username.$touch()"
|
||||||
/>
|
/>
|
||||||
</sw-input-group>
|
</sw-input-group>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2">
|
|
||||||
<sw-input-group :label="$t('wizard.database.password')">
|
<sw-input-group :label="$t('wizard.database.password')">
|
||||||
<sw-input
|
<sw-input
|
||||||
v-model.trim="databaseData.database_password"
|
v-model.trim="databaseData.database_password"
|
||||||
@ -102,7 +81,9 @@
|
|||||||
name="name"
|
name="name"
|
||||||
/>
|
/>
|
||||||
</sw-input-group>
|
</sw-input-group>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2">
|
||||||
<sw-input-group
|
<sw-input-group
|
||||||
:label="$t('wizard.database.host')"
|
:label="$t('wizard.database.host')"
|
||||||
:error="hostnameError"
|
:error="hostnameError"
|
||||||
@ -141,7 +122,7 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
SaveIcon,
|
SaveIcon,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
configData: {
|
configData: {
|
||||||
type: Object,
|
type: Object,
|
||||||
require: true,
|
require: true,
|
||||||
@ -168,7 +149,6 @@ export default {
|
|||||||
database_username: null,
|
database_username: null,
|
||||||
database_password: null,
|
database_password: null,
|
||||||
app_url: window.location.origin,
|
app_url: window.location.origin,
|
||||||
app_domain: window.location.origin.replace(/(^\w+:|^)\/\//, ''),
|
|
||||||
},
|
},
|
||||||
connections: ['sqlite', 'mysql', 'pgsql', 'sqlsrv'],
|
connections: ['sqlite', 'mysql', 'pgsql', 'sqlsrv'],
|
||||||
}
|
}
|
||||||
@ -197,12 +177,6 @@ export default {
|
|||||||
return this.$utils.checkValidUrl(val)
|
return this.$utils.checkValidUrl(val)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
app_domain: {
|
|
||||||
required,
|
|
||||||
isUrl(val) {
|
|
||||||
return this.$utils.checkValidDomainUrl(val)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -219,19 +193,6 @@ export default {
|
|||||||
return this.$tc('validation.invalid_url')
|
return this.$tc('validation.invalid_url')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
domainError() {
|
|
||||||
if (!this.$v.databaseData.app_domain.$error) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.$v.databaseData.app_domain.required) {
|
|
||||||
return this.$tc('validation.required')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.$v.databaseData.app_domain.isUrl) {
|
|
||||||
return this.$tc('validation.invalid_domain_url')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
connectionError() {
|
connectionError() {
|
||||||
if (!this.$v.databaseData.database_connection.$error) {
|
if (!this.$v.databaseData.database_connection.$error) {
|
||||||
return ''
|
return ''
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<form action="" @submit.prevent="next()">
|
<form action="" @submit.prevent="next()">
|
||||||
<div>
|
<div>
|
||||||
<div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6">
|
<div class="grid grid-cols-1 gap-5 md:grid-cols-2 lg:mb-6 md:mb-6">
|
||||||
<sw-input-group
|
<sw-input-group
|
||||||
:label="$t('wizard.database.app_url')"
|
:label="$t('wizard.database.app_url')"
|
||||||
:error="urlError"
|
:error="urlError"
|
||||||
@ -16,23 +16,6 @@
|
|||||||
/>
|
/>
|
||||||
</sw-input-group>
|
</sw-input-group>
|
||||||
|
|
||||||
<sw-input-group
|
|
||||||
:label="$t('wizard.database.app_domain')"
|
|
||||||
:error="domainError"
|
|
||||||
required
|
|
||||||
>
|
|
||||||
<sw-input
|
|
||||||
:invalid="$v.databaseData.app_domain.$error"
|
|
||||||
v-model.trim="databaseData.app_domain"
|
|
||||||
type="text"
|
|
||||||
name="name"
|
|
||||||
placeholder="crater.com"
|
|
||||||
@input="$v.databaseData.app_domain.$touch()"
|
|
||||||
/>
|
|
||||||
</sw-input-group>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6">
|
|
||||||
<sw-input-group
|
<sw-input-group
|
||||||
:label="$t('wizard.database.connection')"
|
:label="$t('wizard.database.connection')"
|
||||||
:error="connectionError"
|
:error="connectionError"
|
||||||
@ -62,9 +45,7 @@
|
|||||||
@input="$v.databaseData.database_port.$touch()"
|
@input="$v.databaseData.database_port.$touch()"
|
||||||
/>
|
/>
|
||||||
</sw-input-group>
|
</sw-input-group>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6">
|
|
||||||
<sw-input-group
|
<sw-input-group
|
||||||
:label="$t('wizard.database.db_name')"
|
:label="$t('wizard.database.db_name')"
|
||||||
:error="nameError"
|
:error="nameError"
|
||||||
@ -92,9 +73,7 @@
|
|||||||
@input="$v.databaseData.database_username.$touch()"
|
@input="$v.databaseData.database_username.$touch()"
|
||||||
/>
|
/>
|
||||||
</sw-input-group>
|
</sw-input-group>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2">
|
|
||||||
<sw-input-group :label="$t('wizard.database.password')">
|
<sw-input-group :label="$t('wizard.database.password')">
|
||||||
<sw-input
|
<sw-input
|
||||||
v-model.trim="databaseData.database_password"
|
v-model.trim="databaseData.database_password"
|
||||||
@ -134,8 +113,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { SaveIcon } from '@vue-hero-icons/outline'
|
import { SaveIcon } from '@vue-hero-icons/outline'
|
||||||
import { validationMixin } from 'vuelidate'
|
const { required, numeric } = require('vuelidate/lib/validators')
|
||||||
const { required, numeric, url } = require('vuelidate/lib/validators')
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -168,12 +146,11 @@ export default {
|
|||||||
database_username: null,
|
database_username: null,
|
||||||
database_password: null,
|
database_password: null,
|
||||||
app_url: window.location.origin,
|
app_url: window.location.origin,
|
||||||
app_domain: window.location.origin.replace(/(^\w+:|^)\/\//, ''),
|
|
||||||
},
|
},
|
||||||
connections: ['sqlite', 'mysql', 'pgsql', 'sqlsrv'],
|
connections: ['sqlite', 'mysql', 'pgsql', 'sqlsrv'],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
urlError() {
|
urlError() {
|
||||||
if (!this.$v.databaseData.app_url.$error) {
|
if (!this.$v.databaseData.app_url.$error) {
|
||||||
return ''
|
return ''
|
||||||
@ -187,19 +164,6 @@ export default {
|
|||||||
return this.$tc('validation.invalid_url')
|
return this.$tc('validation.invalid_url')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
domainError() {
|
|
||||||
if (!this.$v.databaseData.app_domain.$error) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.$v.databaseData.app_domain.required) {
|
|
||||||
return this.$tc('validation.required')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.$v.databaseData.app_domain.isUrl) {
|
|
||||||
return this.$tc('validation.invalid_domain_url')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
connectionError() {
|
connectionError() {
|
||||||
if (!this.$v.databaseData.database_connection.$error) {
|
if (!this.$v.databaseData.database_connection.$error) {
|
||||||
return ''
|
return ''
|
||||||
@ -274,12 +238,6 @@ export default {
|
|||||||
return this.$utils.checkValidUrl(val)
|
return this.$utils.checkValidUrl(val)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
app_domain: {
|
|
||||||
required,
|
|
||||||
isUrl(val) {
|
|
||||||
return this.$utils.checkValidDomainUrl(val)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<form action="" @submit.prevent="next()">
|
<form action="" @submit.prevent="next()">
|
||||||
<div>
|
<div>
|
||||||
<div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6">
|
<div class="grid grid-cols-1 gap-5 md:grid-cols-2 lg:mb-6 md:mb-6">
|
||||||
<sw-input-group
|
<sw-input-group
|
||||||
:label="$t('wizard.database.app_url')"
|
:label="$t('wizard.database.app_url')"
|
||||||
:error="urlError"
|
:error="urlError"
|
||||||
@ -16,23 +16,6 @@
|
|||||||
/>
|
/>
|
||||||
</sw-input-group>
|
</sw-input-group>
|
||||||
|
|
||||||
<sw-input-group
|
|
||||||
:label="$t('wizard.database.app_domain')"
|
|
||||||
:error="domainError"
|
|
||||||
required
|
|
||||||
>
|
|
||||||
<sw-input
|
|
||||||
:invalid="$v.databaseData.app_domain.$error"
|
|
||||||
v-model.trim="databaseData.app_domain"
|
|
||||||
type="text"
|
|
||||||
name="name"
|
|
||||||
placeholder="crater.com"
|
|
||||||
@input="$v.databaseData.app_domain.$touch()"
|
|
||||||
/>
|
|
||||||
</sw-input-group>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6">
|
|
||||||
<sw-input-group
|
<sw-input-group
|
||||||
:label="$t('wizard.database.connection')"
|
:label="$t('wizard.database.connection')"
|
||||||
:error="connectionError"
|
:error="connectionError"
|
||||||
@ -81,8 +64,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { SaveIcon } from '@vue-hero-icons/outline'
|
import { SaveIcon } from '@vue-hero-icons/outline'
|
||||||
import { validationMixin } from 'vuelidate'
|
const { required } = require('vuelidate/lib/validators')
|
||||||
const { required, numeric, url } = require('vuelidate/lib/validators')
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -111,7 +93,6 @@ export default {
|
|||||||
database_connection: 'mysql',
|
database_connection: 'mysql',
|
||||||
database_name: null,
|
database_name: null,
|
||||||
app_url: window.location.origin,
|
app_url: window.location.origin,
|
||||||
app_domain: window.location.origin.replace(/(^\w+:|^)\/\//, ''),
|
|
||||||
},
|
},
|
||||||
connections: ['sqlite', 'mysql', 'pgsql', 'sqlsrv'],
|
connections: ['sqlite', 'mysql', 'pgsql', 'sqlsrv'],
|
||||||
}
|
}
|
||||||
@ -130,12 +111,6 @@ export default {
|
|||||||
return this.$utils.checkValidUrl(val)
|
return this.$utils.checkValidUrl(val)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
app_domain: {
|
|
||||||
required,
|
|
||||||
isUrl(val) {
|
|
||||||
return this.$utils.checkValidDomainUrl(val)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -152,19 +127,6 @@ export default {
|
|||||||
return this.$tc('validation.invalid_url')
|
return this.$tc('validation.invalid_url')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
domainError() {
|
|
||||||
if (!this.$v.databaseData.app_domain.$error) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.$v.databaseData.app_domain.required) {
|
|
||||||
return this.$tc('validation.required')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.$v.databaseData.app_domain.isUrl) {
|
|
||||||
return this.$tc('validation.invalid_domain_url')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
connectionError() {
|
connectionError() {
|
||||||
if (!this.$v.databaseData.database_connection.$error) {
|
if (!this.$v.databaseData.database_connection.$error) {
|
||||||
return ''
|
return ''
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<form action="" @submit.prevent="next()">
|
<form action="" @submit.prevent="next()">
|
||||||
<div>
|
<div>
|
||||||
<div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6">
|
<div class="grid grid-cols-1 gap-5 md:grid-cols-2 lg:mb-6 md:mb-6">
|
||||||
<sw-input-group
|
<sw-input-group
|
||||||
:label="$t('wizard.database.app_url')"
|
:label="$t('wizard.database.app_url')"
|
||||||
:error="urlError"
|
:error="urlError"
|
||||||
@ -16,23 +16,6 @@
|
|||||||
/>
|
/>
|
||||||
</sw-input-group>
|
</sw-input-group>
|
||||||
|
|
||||||
<sw-input-group
|
|
||||||
:label="$t('wizard.database.app_domain')"
|
|
||||||
:error="domainError"
|
|
||||||
required
|
|
||||||
>
|
|
||||||
<sw-input
|
|
||||||
:invalid="$v.databaseData.app_domain.$error"
|
|
||||||
v-model.trim="databaseData.app_domain"
|
|
||||||
type="text"
|
|
||||||
name="name"
|
|
||||||
placeholder="crater.com"
|
|
||||||
@input="$v.databaseData.app_domain.$touch()"
|
|
||||||
/>
|
|
||||||
</sw-input-group>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6">
|
|
||||||
<sw-input-group
|
<sw-input-group
|
||||||
:label="$t('wizard.database.connection')"
|
:label="$t('wizard.database.connection')"
|
||||||
:error="connectionError"
|
:error="connectionError"
|
||||||
@ -62,9 +45,7 @@
|
|||||||
@input="$v.databaseData.database_port.$touch()"
|
@input="$v.databaseData.database_port.$touch()"
|
||||||
/>
|
/>
|
||||||
</sw-input-group>
|
</sw-input-group>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-4 mb-4 md:grid-cols-2 lg:mb-6 md:mb-6">
|
|
||||||
<sw-input-group
|
<sw-input-group
|
||||||
:label="$t('wizard.database.db_name')"
|
:label="$t('wizard.database.db_name')"
|
||||||
:error="nameError"
|
:error="nameError"
|
||||||
@ -92,9 +73,7 @@
|
|||||||
@input="$v.databaseData.database_username.$touch()"
|
@input="$v.databaseData.database_username.$touch()"
|
||||||
/>
|
/>
|
||||||
</sw-input-group>
|
</sw-input-group>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-4 mb-6 md:grid-cols-2">
|
|
||||||
<sw-input-group :label="$t('wizard.database.password')">
|
<sw-input-group :label="$t('wizard.database.password')">
|
||||||
<sw-input
|
<sw-input
|
||||||
v-model.trim="databaseData.database_password"
|
v-model.trim="databaseData.database_password"
|
||||||
@ -134,14 +113,13 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { SaveIcon } from '@vue-hero-icons/outline'
|
import { SaveIcon } from '@vue-hero-icons/outline'
|
||||||
import { validationMixin } from 'vuelidate'
|
const { required, numeric } = require('vuelidate/lib/validators')
|
||||||
const { required, numeric, url } = require('vuelidate/lib/validators')
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
SaveIcon,
|
SaveIcon,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
configData: {
|
configData: {
|
||||||
type: Object,
|
type: Object,
|
||||||
require: true,
|
require: true,
|
||||||
@ -168,7 +146,6 @@ export default {
|
|||||||
database_username: null,
|
database_username: null,
|
||||||
database_password: null,
|
database_password: null,
|
||||||
app_url: window.location.origin,
|
app_url: window.location.origin,
|
||||||
app_domain: window.location.origin.replace(/(^\w+:|^)\/\//, ''),
|
|
||||||
},
|
},
|
||||||
connections: ['sqlite', 'mysql', 'pgsql', 'sqlsrv'],
|
connections: ['sqlite', 'mysql', 'pgsql', 'sqlsrv'],
|
||||||
}
|
}
|
||||||
@ -197,12 +174,6 @@ export default {
|
|||||||
return this.$utils.checkValidUrl(val)
|
return this.$utils.checkValidUrl(val)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
app_domain: {
|
|
||||||
required,
|
|
||||||
isUrl(val) {
|
|
||||||
return this.$utils.checkValidDomainUrl(val)
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -219,19 +190,6 @@ export default {
|
|||||||
return this.$tc('validation.invalid_url')
|
return this.$tc('validation.invalid_url')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
domainError() {
|
|
||||||
if (!this.$v.databaseData.app_domain.$error) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.$v.databaseData.app_domain.required) {
|
|
||||||
return this.$tc('validation.required')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.$v.databaseData.app_domain.isUrl) {
|
|
||||||
return this.$tc('validation.invalid_domain_url')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
connectionError() {
|
connectionError() {
|
||||||
if (!this.$v.databaseData.database_connection.$error) {
|
if (!this.$v.databaseData.database_connection.$error) {
|
||||||
return ''
|
return ''
|
||||||
@ -282,7 +240,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
for (const key in this.databaseData) {
|
for (const key in this.databaseData) {
|
||||||
if (this.configData.hasOwnProperty(key)) {
|
if (this.configData.hasOwnProperty(key)) {
|
||||||
this.databaseData[key] = this.configData[key]
|
this.databaseData[key] = this.configData[key]
|
||||||
|
|||||||
@ -36,8 +36,10 @@ use Crater\Http\Controllers\V1\Invoice\SendInvoiceController;
|
|||||||
use Crater\Http\Controllers\V1\Item\ItemsController;
|
use Crater\Http\Controllers\V1\Item\ItemsController;
|
||||||
use Crater\Http\Controllers\V1\Item\UnitsController;
|
use Crater\Http\Controllers\V1\Item\UnitsController;
|
||||||
use Crater\Http\Controllers\V1\Mobile\AuthController;
|
use Crater\Http\Controllers\V1\Mobile\AuthController;
|
||||||
|
use Crater\Http\Controllers\V1\Onboarding\AppDomainController;
|
||||||
use Crater\Http\Controllers\V1\Onboarding\DatabaseConfigurationController;
|
use Crater\Http\Controllers\V1\Onboarding\DatabaseConfigurationController;
|
||||||
use Crater\Http\Controllers\V1\Onboarding\FinishController;
|
use Crater\Http\Controllers\V1\Onboarding\FinishController;
|
||||||
|
use Crater\Http\Controllers\V1\Onboarding\LoginController;
|
||||||
use Crater\Http\Controllers\V1\Onboarding\OnboardingWizardController;
|
use Crater\Http\Controllers\V1\Onboarding\OnboardingWizardController;
|
||||||
use Crater\Http\Controllers\V1\Onboarding\PermissionsController;
|
use Crater\Http\Controllers\V1\Onboarding\PermissionsController;
|
||||||
use Crater\Http\Controllers\V1\Onboarding\RequirementsController;
|
use Crater\Http\Controllers\V1\Onboarding\RequirementsController;
|
||||||
@ -133,12 +135,17 @@ Route::prefix('/v1')->group(function () {
|
|||||||
|
|
||||||
Route::get('/onboarding/database/config', [DatabaseConfigurationController::class, 'getDatabaseEnvironment']);
|
Route::get('/onboarding/database/config', [DatabaseConfigurationController::class, 'getDatabaseEnvironment']);
|
||||||
|
|
||||||
|
Route::put('/onboarding/set-domain', AppDomainController::class);
|
||||||
|
|
||||||
|
Route::post('/onboarding/login', LoginController::class);
|
||||||
|
|
||||||
Route::post('/onboarding/finish', FinishController::class);
|
Route::post('/onboarding/finish', FinishController::class);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
Route::middleware(['auth:sanctum', 'admin'])->group(function () {
|
Route::middleware(['auth:sanctum', 'admin'])->group(function () {
|
||||||
|
|
||||||
|
|
||||||
// Bootstrap
|
// Bootstrap
|
||||||
//----------------------------------
|
//----------------------------------
|
||||||
|
|
||||||
@ -151,6 +158,12 @@ Route::prefix('/v1')->group(function () {
|
|||||||
Route::get('/dashboard', DashboardController::class);
|
Route::get('/dashboard', DashboardController::class);
|
||||||
|
|
||||||
|
|
||||||
|
// Auth check
|
||||||
|
//----------------------------------
|
||||||
|
|
||||||
|
Route::get('/auth/check', [AuthController::class, 'check']);
|
||||||
|
|
||||||
|
|
||||||
// Search users
|
// Search users
|
||||||
//----------------------------------
|
//----------------------------------
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user