Merge branch 'develop'
# Conflicts: # public/css/app.css # public/js/app.js
This commit is contained in:
@@ -68,6 +68,7 @@ class Kernel extends HttpKernel
|
|||||||
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
|
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||||
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
|
||||||
'can' => \Illuminate\Auth\Middleware\Authorize::class,
|
'can' => \Illuminate\Auth\Middleware\Authorize::class,
|
||||||
|
'has.access' => \App\Http\Middleware\HasAccessToThisGroup::class,
|
||||||
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||||
'global.api.authenticated' => \App\Http\Middleware\GlobalApiAuthenticated::class,
|
'global.api.authenticated' => \App\Http\Middleware\GlobalApiAuthenticated::class,
|
||||||
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
|
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class Demo
|
|||||||
protected $safeRoutes = [
|
protected $safeRoutes = [
|
||||||
'login',
|
'login',
|
||||||
'logout',
|
'logout',
|
||||||
//'profile/toggle-theme'
|
'profile/toggle-theme'
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $allowedIps = [
|
protected $allowedIps = [
|
||||||
|
|||||||
27
app/Http/Middleware/HasAccessToThisGroup.php
Normal file
27
app/Http/Middleware/HasAccessToThisGroup.php
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
|
||||||
|
class HasAccessToThisGroup
|
||||||
|
{
|
||||||
|
public function handle(Request $request, Closure $next, $group)
|
||||||
|
{
|
||||||
|
if ($group === 'servers') {
|
||||||
|
$package = $request->user()->package ?? [];
|
||||||
|
|
||||||
|
if (
|
||||||
|
!Arr::get($package->server_permissions, 'create', false) &&
|
||||||
|
!Arr::get($package->server_permissions, 'update', false) &&
|
||||||
|
!Arr::get($package->server_permissions, 'delete', false)
|
||||||
|
) {
|
||||||
|
abort(404);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,9 @@ namespace App\Models;
|
|||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property mixed|string domain
|
||||||
|
*/
|
||||||
class Site extends Model
|
class Site extends Model
|
||||||
{
|
{
|
||||||
const STATUS_BUSY = 'busy';
|
const STATUS_BUSY = 'busy';
|
||||||
@@ -95,6 +98,10 @@ class Site extends Model
|
|||||||
|
|
||||||
public static function booted()
|
public static function booted()
|
||||||
{
|
{
|
||||||
|
static::creating(function (self $site) {
|
||||||
|
$site->domain = strtolower($site->domain);
|
||||||
|
});
|
||||||
|
|
||||||
static::created(function (self $site) {
|
static::created(function (self $site) {
|
||||||
$site->systemUsers()->create();
|
$site->systemUsers()->create();
|
||||||
});
|
});
|
||||||
|
|||||||
160768
public/css/app.css
vendored
160768
public/css/app.css
vendored
File diff suppressed because one or more lines are too long
27335
public/js/app.js
vendored
27335
public/js/app.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<TopBar :breadcrumbs="breadcrumbs" />
|
<TopBar :breadcrumbs="breadcrumbs"/>
|
||||||
|
|
||||||
<Content>
|
<Content>
|
||||||
<Container>
|
<Container>
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<PageBody>
|
<PageBody>
|
||||||
<div>
|
<div>
|
||||||
<ul class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
<ul class="grid grid-cols-1 gap-4" :class="{'md:grid-cols-3': hasAccessToServers, 'md:grid-cols-2': !hasAccessToServers}">
|
||||||
<li class="p-6 rounded shadow bg-surface-3 transform transition duration-fast ease-in-out hover:scale-95">
|
<li class="p-6 rounded shadow bg-surface-3 transform transition duration-fast ease-in-out hover:scale-95">
|
||||||
<inertia-link :href="route('sites.index')" class="flex space-x-4">
|
<inertia-link :href="route('sites.index')" class="flex space-x-4">
|
||||||
<div>
|
<div>
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</inertia-link>
|
</inertia-link>
|
||||||
</li>
|
</li>
|
||||||
<li class="p-6 rounded shadow bg-surface-3 transform transition duration-fast ease-in-out hover:scale-95">
|
<li class="p-6 rounded shadow bg-surface-3 transform transition duration-fast ease-in-out hover:scale-95" v-if="hasAccessToServers">
|
||||||
<inertia-link :href="route('servers.index')" class="flex space-x-4">
|
<inertia-link :href="route('servers.index')" class="flex space-x-4">
|
||||||
<div>
|
<div>
|
||||||
<IconStorage class="w-6 h-6"/>
|
<IconStorage class="w-6 h-6"/>
|
||||||
@@ -36,7 +36,9 @@
|
|||||||
</inertia-link>
|
</inertia-link>
|
||||||
</li>
|
</li>
|
||||||
<li class="p-6 rounded shadow bg-surface-3 transform transition duration-fast ease-in-out hover:scale-95">
|
<li class="p-6 rounded shadow bg-surface-3 transform transition duration-fast ease-in-out hover:scale-95">
|
||||||
<inertia-link :href="$page.props.settings.billing ? route('profile.billing.index') : route('profile.index')" class="flex space-x-4">
|
<inertia-link
|
||||||
|
:href="$page.props.settings.billing ? route('profile.billing.index') : route('profile.index')"
|
||||||
|
class="flex space-x-4">
|
||||||
<div>
|
<div>
|
||||||
<IconBox class="w-6 h-6"/>
|
<IconBox class="w-6 h-6"/>
|
||||||
</div>
|
</div>
|
||||||
@@ -55,7 +57,8 @@
|
|||||||
{{ log.title }}
|
{{ log.title }}
|
||||||
</template>
|
</template>
|
||||||
<template #subtitle>{{ log.description }}</template>
|
<template #subtitle>{{ log.description }}</template>
|
||||||
<template #suffix><span class="text-medium-emphasis">{{ log.created_at_human }}</span></template>
|
<template #suffix><span class="text-medium-emphasis">{{ log.created_at_human }}</span>
|
||||||
|
</template>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
</PageBody>
|
</PageBody>
|
||||||
@@ -65,86 +68,92 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import TopBar from './components/TopBar'
|
import TopBar from './components/TopBar'
|
||||||
import Container from '@/components/Container'
|
import Container from '@/components/Container'
|
||||||
import Content from '@/components/Content'
|
import Content from '@/components/Content'
|
||||||
import Page from '@/components/Page'
|
import Page from '@/components/Page'
|
||||||
import PageHeader from '@/components/PageHeader'
|
import PageHeader from '@/components/PageHeader'
|
||||||
import PageHeaderTitle from '@/components/PageHeaderTitle'
|
import PageHeaderTitle from '@/components/PageHeaderTitle'
|
||||||
import PageBody from '@/components/PageBody'
|
import PageBody from '@/components/PageBody'
|
||||||
import Button from '@/components/Button'
|
import Button from '@/components/Button'
|
||||||
import List from '@/components/List'
|
import List from '@/components/List'
|
||||||
import ListItem from '@/components/ListItem'
|
import ListItem from '@/components/ListItem'
|
||||||
import StatusBubble from '@/components/StatusBubble'
|
import StatusBubble from '@/components/StatusBubble'
|
||||||
import NotificationBadge from '@/components/NotificationBadge'
|
import NotificationBadge from '@/components/NotificationBadge'
|
||||||
import MainLayout from '@/Layouts/MainLayout'
|
import MainLayout from '@/Layouts/MainLayout'
|
||||||
import IconBox from '@/components/icons/IconBox'
|
import IconBox from '@/components/icons/IconBox'
|
||||||
import IconGlobe from '@/components/icons/IconGlobe'
|
import IconGlobe from '@/components/icons/IconGlobe'
|
||||||
import IconStorage from '@/components/icons/IconStorage'
|
import IconStorage from '@/components/icons/IconStorage'
|
||||||
|
|
||||||
import { useNotification } from '@/hooks/notification'
|
import {useNotification} from '@/hooks/notification'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
metaInfo() {
|
metaInfo() {
|
||||||
return {
|
return {
|
||||||
title: `${this.__('Dashboard')}`,
|
title: `${this.__('Dashboard')}`,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
layout: MainLayout,
|
layout: MainLayout,
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
TopBar,
|
TopBar,
|
||||||
Container,
|
Container,
|
||||||
Content,
|
Content,
|
||||||
Page,
|
Page,
|
||||||
PageHeader,
|
PageHeader,
|
||||||
PageHeaderTitle,
|
PageHeaderTitle,
|
||||||
PageBody,
|
PageBody,
|
||||||
Button,
|
Button,
|
||||||
List,
|
List,
|
||||||
ListItem,
|
ListItem,
|
||||||
StatusBubble,
|
StatusBubble,
|
||||||
NotificationBadge,
|
NotificationBadge,
|
||||||
IconBox,
|
IconBox,
|
||||||
IconGlobe,
|
IconGlobe,
|
||||||
IconStorage,
|
IconStorage,
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
sites: Number,
|
sites: Number,
|
||||||
servers: Number,
|
servers: Number,
|
||||||
package: Object,
|
package: Object,
|
||||||
logs: Array,
|
logs: Array,
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
useNotification
|
useNotification
|
||||||
},
|
},
|
||||||
|
|
||||||
data () {
|
data() {
|
||||||
return{
|
return {
|
||||||
breadcrumbs: [
|
breadcrumbs: [
|
||||||
{
|
{
|
||||||
title: this.$page.props.settings.name,
|
title: this.$page.props.settings.name,
|
||||||
to: '/',
|
to: '/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Dashboard',
|
title: 'Dashboard',
|
||||||
to: '/',
|
to: '/',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
computed: {
|
||||||
if (this.$page.props.flash.info) {
|
hasAccessToServers () {
|
||||||
useNotification({
|
return (this.$page.props.auth.can.servers.create || this.$page.props.auth.can.servers.update || this.$page.props.auth.can.servers.delete);
|
||||||
variant: 'info',
|
}
|
||||||
title: `Information`,
|
},
|
||||||
message: this.$page.props.flash.info,
|
|
||||||
})
|
mounted() {
|
||||||
}
|
if (this.$page.props.flash.info) {
|
||||||
},
|
useNotification({
|
||||||
}
|
variant: 'info',
|
||||||
|
title: `Information`,
|
||||||
|
message: this.$page.props.flash.info,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -29,6 +29,14 @@ export default {
|
|||||||
breadcrumbs: Array,
|
breadcrumbs: Array,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
hasServerAccess() {
|
||||||
|
return this.$page.props.auth.can.servers.create ||
|
||||||
|
this.$page.props.auth.can.servers.delete ||
|
||||||
|
this.$page.props.auth.can.servers.update
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tabBars: [
|
tabBars: [
|
||||||
@@ -41,10 +49,10 @@ export default {
|
|||||||
title: this.__('Sites'),
|
title: this.__('Sites'),
|
||||||
to: this.route('sites.index'),
|
to: this.route('sites.index'),
|
||||||
},
|
},
|
||||||
{
|
(this.$page.props.auth.can.servers.create || this.$page.props.auth.can.servers.update || this.$page.props.auth.can.servers.delete) ? {
|
||||||
title: this.__('Servers'),
|
title: this.__('Servers'),
|
||||||
to: this.route('servers.index'),
|
to: this.route('servers.index'),
|
||||||
},
|
} : null,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -42,10 +42,10 @@ export default {
|
|||||||
to: this.route('sites.index'),
|
to: this.route('sites.index'),
|
||||||
active: this.route().current('sites.*')
|
active: this.route().current('sites.*')
|
||||||
},
|
},
|
||||||
{
|
(this.$page.props.auth.can.servers.create || this.$page.props.auth.can.servers.update || this.$page.props.auth.can.servers.delete) ? {
|
||||||
title: 'Servers',
|
title: this.__('Servers'),
|
||||||
to: this.route('servers.index'),
|
to: this.route('servers.index'),
|
||||||
},
|
} : null,
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
35
resources/sass/app.scss
vendored
35
resources/sass/app.scss
vendored
@@ -5,8 +5,6 @@
|
|||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@import 'nprogress';
|
@import 'nprogress';
|
||||||
|
|
||||||
//$balloon-bg: var(--color-surface-1);
|
|
||||||
@import "~balloon-css/src/balloon";
|
@import "~balloon-css/src/balloon";
|
||||||
|
|
||||||
.bf-blur {
|
.bf-blur {
|
||||||
@@ -29,3 +27,36 @@
|
|||||||
-webkit-background-clip: text;
|
-webkit-background-clip: text;
|
||||||
-webkit-text-fill-color: transparent;
|
-webkit-text-fill-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.theme--dark {
|
||||||
|
.prose {
|
||||||
|
color: var(--text-medium-emphasis);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vue-simplemde {
|
||||||
|
.editor-toolbar {
|
||||||
|
border-left: 1px solid var(--color-surface-3);
|
||||||
|
border-top: 1px solid var(--color-surface-3);
|
||||||
|
border-right: 1px solid var(--color-surface-3);
|
||||||
|
|
||||||
|
.separator {
|
||||||
|
border-left: 1px solid var(--color-surface-3);
|
||||||
|
border-right: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--text-medium-emphasis) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
background: var(--color-surface-3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror {
|
||||||
|
background: var(--color-surface-1);
|
||||||
|
color: var(--text-medium-emphasis);
|
||||||
|
border: 1px solid var(--color-surface-3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ Route::group(['middleware' => ['auth', 'auth.blocked']], function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Server routes
|
// Server routes
|
||||||
Route::group(['prefix' => 'servers', 'as' => 'servers.'], function () {
|
Route::group(['prefix' => 'servers', 'as' => 'servers.', 'middleware' => 'has.access:servers'], function () {
|
||||||
Route::get('/', 'ServerController@index')->name('index');
|
Route::get('/', 'ServerController@index')->name('index');
|
||||||
Route::get('{provider}/plans-and-regions', 'ServerController@plansAndRegions')->name('plans-and-regions');
|
Route::get('{provider}/plans-and-regions', 'ServerController@plansAndRegions')->name('plans-and-regions');
|
||||||
Route::get('{server}', 'ServerController@show')->name('show');
|
Route::get('{server}', 'ServerController@show')->name('show');
|
||||||
|
|||||||
Reference in New Issue
Block a user