mirror of
https://github.com/linuxserver/Heimdall.git
synced 2026-02-24 13:40:32 +09:00
Compare commits
183 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
181b7564e8 | ||
|
|
0d3640b67a | ||
|
|
82b209d4b5 | ||
|
|
f576a82803 | ||
|
|
bb07ba5964 | ||
|
|
9aaa900a3e | ||
|
|
07f07449b9 | ||
|
|
2836dadf1a | ||
|
|
4a90fdf22d | ||
|
|
0de56e5876 | ||
|
|
d886b44c1e | ||
|
|
898ee6915d | ||
|
|
f6eae7f25f | ||
|
|
c1255280aa | ||
|
|
5514d893f8 | ||
|
|
c4d5ca43dd | ||
|
|
a90bcb1151 | ||
|
|
ffc736ada6 | ||
|
|
966027faf5 | ||
|
|
1111bf72d6 | ||
|
|
cc6e47372e | ||
|
|
256160727c | ||
|
|
0299ee6fa9 | ||
|
|
8957a2f49f | ||
|
|
756ab353f3 | ||
|
|
76f0b84827 | ||
|
|
68c8dbc33a | ||
|
|
b1e856ccfc | ||
|
|
44fb923b7f | ||
|
|
8bad474808 | ||
|
|
9a80064a50 | ||
|
|
e86c5e601d | ||
|
|
c4bf619be4 | ||
|
|
4b29b476df | ||
|
|
3a39809585 | ||
|
|
157b972ff5 | ||
|
|
71b15a5aed | ||
|
|
b50bf716dc | ||
|
|
722d00df5f | ||
|
|
54679ff9eb | ||
|
|
4c7e56e6fe | ||
|
|
7b0ae66101 | ||
|
|
48616e87bd | ||
|
|
f9280cd4c0 | ||
|
|
3124a01011 | ||
|
|
ec27889086 | ||
|
|
aba1f37b1c | ||
|
|
6565dfde07 | ||
|
|
aa98c3505c | ||
|
|
15f5c3e5be | ||
|
|
fc2d153ded | ||
|
|
4a7690147e | ||
|
|
7d32e6edb0 | ||
|
|
3d1fc80d64 | ||
|
|
8b0700e9ef | ||
|
|
cc241f1bd6 | ||
|
|
810ee03965 | ||
|
|
7809abb376 | ||
|
|
2f3b7e52db | ||
|
|
fdd5a78eb8 | ||
|
|
98401f20a2 | ||
|
|
30663e4d5e | ||
|
|
8972a11c0a | ||
|
|
bf349eec7a | ||
|
|
cb314a4fd9 | ||
|
|
1a78c8077a | ||
|
|
a3c75b2dd4 | ||
|
|
ee77d09c58 | ||
|
|
0966639699 | ||
|
|
153bb0e91d | ||
|
|
0c7a60a5c7 | ||
|
|
edb51e56f1 | ||
|
|
99193a578e | ||
|
|
49b5d57e14 | ||
|
|
716d5a2f69 | ||
|
|
62340b07a9 | ||
|
|
2312e8b648 | ||
|
|
b390a719e9 | ||
|
|
d4f7ad842c | ||
|
|
5c2501c1a7 | ||
|
|
198ffd7665 | ||
|
|
7cf9d46eb3 | ||
|
|
66dbbc835e | ||
|
|
178e46ca05 | ||
|
|
27f58c0866 | ||
|
|
43f894b58d | ||
|
|
b83f24c6f3 | ||
|
|
b22fbdbad1 | ||
|
|
6552a8c061 | ||
|
|
bcd6f72b72 | ||
|
|
d4fe699029 | ||
|
|
db8fa38665 | ||
|
|
df41de3a9a | ||
|
|
b3070bc8f9 | ||
|
|
487cdc483c | ||
|
|
dcc0f90b23 | ||
|
|
75014c8269 | ||
|
|
386e4c788b | ||
|
|
fe0109494e | ||
|
|
6907695c5d | ||
|
|
533af2dc49 | ||
|
|
1ac5eb6d23 | ||
|
|
ca557fcaf1 | ||
|
|
e2ba89c80e | ||
|
|
bbae811cd8 | ||
|
|
589aa73a15 | ||
|
|
fc023401f5 | ||
|
|
1a4b6da3ea | ||
|
|
02b82dc740 | ||
|
|
4e5129ab8f | ||
|
|
62d9b0cc76 | ||
|
|
02dfed0bc7 | ||
|
|
71d356935f | ||
|
|
e53bae2c69 | ||
|
|
3117b9c483 | ||
|
|
c5817c9b2e | ||
|
|
c403e8b2df | ||
|
|
1ca403cc6e | ||
|
|
758c174141 | ||
|
|
9bc9c48e06 | ||
|
|
9a6dd623db | ||
|
|
d1c6001fae | ||
|
|
74196a2bfa | ||
|
|
724110dad2 | ||
|
|
3a043e0165 | ||
|
|
ac37c60e1f | ||
|
|
937e576520 | ||
|
|
9086e9bd75 | ||
|
|
4c90d8c87e | ||
|
|
a4cceb3ae0 | ||
|
|
90c21d700d | ||
|
|
15b1f3234b | ||
|
|
a116345d60 | ||
|
|
2b4e6d372c | ||
|
|
d370f2c3ee | ||
|
|
ade09f3b1c | ||
|
|
80aa120086 | ||
|
|
a5cbcaca03 | ||
|
|
f2bfc26c5e | ||
|
|
9f0abb6f4d | ||
|
|
9ca2078e7d | ||
|
|
9e4a06999b | ||
|
|
8b72ff0a0d | ||
|
|
51ddaccc16 | ||
|
|
4ff1a4aec4 | ||
|
|
d5bd614cc6 | ||
|
|
0f498eca75 | ||
|
|
3dac9828c8 | ||
|
|
297c2bb30f | ||
|
|
b1dc4d4a41 | ||
|
|
0fe6565346 | ||
|
|
85c68c1f46 | ||
|
|
fc2191b8db | ||
|
|
ee36a0cfae | ||
|
|
a868a6cac1 | ||
|
|
574756b236 | ||
|
|
f9599079e5 | ||
|
|
10afffb71d | ||
|
|
79d53af339 | ||
|
|
8cc6a9cc63 | ||
|
|
18001fbdd0 | ||
|
|
398df75865 | ||
|
|
41c2983312 | ||
|
|
bd3b882b3a | ||
|
|
e52bc9c6b2 | ||
|
|
a16233ee10 | ||
|
|
5b177f1127 | ||
|
|
f7633b6a5f | ||
|
|
d58e6cb560 | ||
|
|
87fe9c1771 | ||
|
|
95d9e9edb9 | ||
|
|
f7b2c51f9d | ||
|
|
72c70e27f2 | ||
|
|
becbe5ab96 | ||
|
|
f5bce95808 | ||
|
|
1e2b807e05 | ||
|
|
ed3dbf2f14 | ||
|
|
1e35f83fed | ||
|
|
8499d100ff | ||
|
|
bdeae6a722 | ||
|
|
4c63b66dbf | ||
|
|
371f52f92e | ||
|
|
6daaf94974 |
@@ -9,6 +9,13 @@ LOG_CHANNEL=daily
|
||||
DB_CONNECTION=sqlite
|
||||
DB_DATABASE=app.sqlite
|
||||
|
||||
#DB_CONNECTION=<mysql | pgsql>
|
||||
#DB_HOST=<hostname | ip>
|
||||
#DB_PORT=<port number>
|
||||
#DB_DATABASE=<database>
|
||||
#DB_USERNAME=<user>
|
||||
#DB_PASSWORD=<password>
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=file
|
||||
QUEUE_CONNECTION=sync
|
||||
|
||||
53
.github/workflows/ci.yml
vendored
Normal file
53
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
name: Tests (PHP)
|
||||
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
name: Run tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
|
||||
- name: Setup PHP, with composer and extensions
|
||||
uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php
|
||||
with:
|
||||
php-version: '7.4'
|
||||
extensions: mbstring, dom, fileinfo, mysql, libxml, xml, xmlwriter, dom, tokenizer, filter, json, phar, pcre, openssl, pdo, intl, curl
|
||||
|
||||
- name: Cache composer dependencies
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: vendor
|
||||
key: composer-${{ hashFiles('composer.lock') }}
|
||||
|
||||
- name: Run composer install
|
||||
run: composer install -n --prefer-dist
|
||||
env:
|
||||
APP_ENV: testing
|
||||
|
||||
- name: Prepare Laravel Application
|
||||
run: |
|
||||
cp .env.example .env
|
||||
php artisan key:generate
|
||||
|
||||
- name: Cache yarn dependencies
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: node_modules
|
||||
key: yarn-${{ hashFiles('yarn.lock') }}
|
||||
|
||||
- name: Run yarn
|
||||
run: yarn && yarn dev
|
||||
|
||||
- name: Run tests
|
||||
run: ./vendor/bin/phpunit
|
||||
env:
|
||||
APP_ENV: testing
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@master
|
||||
if: failure()
|
||||
with:
|
||||
name: Logs
|
||||
path: ./storage/logs
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,6 +3,7 @@
|
||||
/public/hot
|
||||
/public/storage
|
||||
/storage/*.key
|
||||
/storage/debugbar
|
||||
/.idea
|
||||
/.vagrant
|
||||
Homestead.json
|
||||
@@ -27,3 +28,4 @@ yarn-error.log
|
||||
.VolumeIcon.icns
|
||||
storage/app/public/avatars/*
|
||||
.env
|
||||
.phpunit.result.cache
|
||||
|
||||
@@ -3,62 +3,185 @@
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class Application extends Model
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public $incrementing = false;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $primaryKey = 'appid';
|
||||
|
||||
//
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function icon()
|
||||
{
|
||||
if(!file_exists(storage_path('app/public/'.$this->icon))) {
|
||||
if (! file_exists(storage_path('app/public/'.$this->icon))) {
|
||||
$img_src = app_path('SupportedApps/'.$this->name.'/'.str_replace('icons/', '', $this->icon));
|
||||
$img_dest = storage_path('app/public/'.$this->icon);
|
||||
//die("i: ".$img_src);
|
||||
@copy($img_src, $img_dest);
|
||||
}
|
||||
|
||||
|
||||
return $this->icon;
|
||||
}
|
||||
|
||||
public function iconView()
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function iconView(): string
|
||||
{
|
||||
return asset('storage/'.$this->icon);
|
||||
}
|
||||
|
||||
public function defaultColour()
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function defaultColour(): string
|
||||
{
|
||||
// check if light or dark
|
||||
if($this->tile_background == 'light') return '#fafbfc';
|
||||
if ($this->tile_background == 'light') {
|
||||
return '#fafbfc';
|
||||
}
|
||||
|
||||
return '#161b1f';
|
||||
}
|
||||
|
||||
public function class()
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function class(): string
|
||||
{
|
||||
$name = $this->name;
|
||||
$name = preg_replace('/\PL/u', '', $name);
|
||||
$name = preg_replace('/[^\p{L}\p{N}]/u', '', $name);
|
||||
|
||||
$class = '\App\SupportedApps\\'.$name.'\\'.$name;
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
public static function applist()
|
||||
/**
|
||||
* @param $name
|
||||
* @return string
|
||||
*/
|
||||
public static function classFromName($name)
|
||||
{
|
||||
$name = preg_replace('/[^\p{L}\p{N}]/u', '', $name);
|
||||
|
||||
$class = '\App\SupportedApps\\'.$name.'\\'.$name;
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public static function apps(): \Illuminate\Support\Collection
|
||||
{
|
||||
$json = json_decode(file_get_contents(storage_path('app/supportedapps.json'))) ?? [];
|
||||
$apps = collect($json->apps);
|
||||
|
||||
return $apps->sortBy('name', SORT_NATURAL | SORT_FLAG_CASE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function autocomplete(): array
|
||||
{
|
||||
$apps = self::apps();
|
||||
$list = [];
|
||||
$all = self::orderBy('name')->get()->sortBy('name', SORT_NATURAL|SORT_FLAG_CASE);
|
||||
$list['null'] = 'None';
|
||||
foreach($all as $app) {
|
||||
$name = $app->name;
|
||||
// $name = preg_replace('/\PL/u', '', $name);
|
||||
$name = preg_replace('/[^\p{L}\p{N}]/u', '', $name);
|
||||
|
||||
$list['\App\SupportedApps\\'.$name.'\\'.$name] = $app->name;
|
||||
foreach ($apps as $app) {
|
||||
$list[] = (object) [
|
||||
'label' => $app->name,
|
||||
'value' => $app->appid,
|
||||
];
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $appid
|
||||
* @return mixed|null
|
||||
*/
|
||||
public static function getApp($appid)
|
||||
{
|
||||
Log::debug("Get app triggered for: $appid");
|
||||
|
||||
$localapp = self::where('appid', $appid)->first();
|
||||
$app = self::single($appid);
|
||||
|
||||
$application = ($localapp) ? $localapp : new self;
|
||||
|
||||
// Files missing? || app not in db || old sha version
|
||||
if (
|
||||
! file_exists(app_path('SupportedApps/'.className($app->name))) ||
|
||||
! $localapp ||
|
||||
$localapp->sha !== $app->sha
|
||||
) {
|
||||
$gotFiles = SupportedApps::getFiles($app);
|
||||
if($gotFiles) {
|
||||
$app = SupportedApps::saveApp($app, $application);
|
||||
}
|
||||
}
|
||||
|
||||
return $app;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $appid
|
||||
* @return mixed|null
|
||||
*/
|
||||
public static function single($appid)
|
||||
{
|
||||
$apps = self::apps();
|
||||
$app = $apps->where('appid', $appid)->first();
|
||||
|
||||
if ($app === null) {
|
||||
// Try in db for Private App
|
||||
$appModel = self::where('appid', $appid)->first();
|
||||
if($appModel) {
|
||||
$app = json_decode($appModel->toJson());
|
||||
}
|
||||
}
|
||||
|
||||
if ($app === null) {
|
||||
return null;
|
||||
}
|
||||
$classname = preg_replace('/[^\p{L}\p{N}]/u', '', $app->name);
|
||||
$app->class = '\App\SupportedApps\\'.$classname.'\\'.$classname;
|
||||
|
||||
return $app;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function applist(): array
|
||||
{
|
||||
$list = [];
|
||||
$list['null'] = 'None';
|
||||
$apps = self::apps();
|
||||
foreach ($apps as $app) {
|
||||
$list[$app->appid] = $app->name;
|
||||
}
|
||||
|
||||
// Check for private apps in the db
|
||||
$appsListFromDB = self::all(['appid', 'name']);
|
||||
|
||||
foreach($appsListFromDB as $app) {
|
||||
// Already existing keys are overwritten,
|
||||
// only private apps should be added at the end
|
||||
$list[$app->appid] = $app->name;
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use App\Application;
|
||||
use App\SupportedApps;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class RegisterApp extends Command
|
||||
{
|
||||
@@ -13,7 +14,7 @@ class RegisterApp extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'register:app {folder}';
|
||||
protected $signature = 'register:app {folder} {--remove}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@@ -40,40 +41,56 @@ class RegisterApp extends Command
|
||||
public function handle()
|
||||
{
|
||||
$folder = $this->argument('folder');
|
||||
if($folder == 'all') {
|
||||
if ($folder == 'all') {
|
||||
$apps = scandir(app_path('SupportedApps'));
|
||||
foreach($apps as $folder) {
|
||||
if($folder == '.' || $folder == '..') continue;
|
||||
foreach ($apps as $folder) {
|
||||
if ($folder == '.' || $folder == '..') {
|
||||
continue;
|
||||
}
|
||||
$this->addApp($folder);
|
||||
}
|
||||
|
||||
} else {
|
||||
$this->addApp($folder);
|
||||
$this->addApp($folder, $this->option('remove'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function addApp($folder)
|
||||
public function addApp($folder, $remove = false)
|
||||
{
|
||||
$json = app_path('SupportedApps/'.$folder.'/app.json');
|
||||
if(file_exists($json)) {
|
||||
$app = json_decode(file_get_contents($json));
|
||||
if(isset($app->appid)) {
|
||||
$exists = Application::find($app->appid);
|
||||
if($exists) {
|
||||
$this->error('Application already registered - '.$exists->name." - ".$exists->appid);
|
||||
} else {
|
||||
// Doesn't exist so add it
|
||||
SupportedApps::saveApp($app, new Application);
|
||||
$this->info("Application Added - ".$app->name." - ".$app->appid);
|
||||
}
|
||||
} else {
|
||||
$this->error('No App ID for - '.$folder);
|
||||
}
|
||||
|
||||
} else {
|
||||
$this->error('Could not find '.$json);
|
||||
|
||||
if (!file_exists($json)) {
|
||||
$this->error('Could not find ' . $json);
|
||||
return;
|
||||
}
|
||||
|
||||
$app = json_decode(file_get_contents($json));
|
||||
|
||||
if (!isset($app->appid)) {
|
||||
$this->error('No App ID for - ' . $folder);
|
||||
return;
|
||||
}
|
||||
|
||||
$exists = Application::find($app->appid);
|
||||
|
||||
if ($exists) {
|
||||
if ($remove) {
|
||||
$exists->delete();
|
||||
$this->info('Application Removed - ' . $app->name . ' - ' . $app->appid);
|
||||
return;
|
||||
}
|
||||
$this->error('Application already registered - ' . $exists->name . ' - ' . $exists->appid);
|
||||
return;
|
||||
}
|
||||
|
||||
// Doesn't exist so add it
|
||||
SupportedApps::saveApp($app, new Application);
|
||||
$this->saveIcon($folder, $app->icon);
|
||||
$this->info('Application Added - ' . $app->name . ' - ' . $app->appid);
|
||||
}
|
||||
|
||||
private function saveIcon($appFolder, $icon) {
|
||||
$iconPath = app_path('SupportedApps/' . $appFolder . '/' . $icon);
|
||||
$contents = file_get_contents($iconPath);
|
||||
Storage::disk('public')->put('icons/'.$icon, $contents);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<?php namespace App;
|
||||
<?php
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
namespace App;
|
||||
|
||||
interface EnhancedApps
|
||||
{
|
||||
public function test();
|
||||
public function livestats();
|
||||
public function url($endpoint);
|
||||
|
||||
}
|
||||
public function livestats();
|
||||
|
||||
public function url($endpoint);
|
||||
}
|
||||
|
||||
@@ -4,13 +4,18 @@ use Illuminate\Support\Str;
|
||||
|
||||
function format_bytes($bytes, $is_drive_size = true, $beforeunit = '', $afterunit = '')
|
||||
{
|
||||
$btype = ($is_drive_size === true) ? 1000 : 1024;
|
||||
$labels = array('B','KB','MB','GB','TB');
|
||||
for($x = 0; $bytes >= $btype && $x < (count($labels) - 1); $bytes /= $btype, $x++); // use 1000 rather than 1024 to simulate HD size not real size
|
||||
if($labels[$x] == "TB") return(round($bytes, 3).$beforeunit.$labels[$x].$afterunit);
|
||||
elseif($labels[$x] == "GB") return(round($bytes, 2).$beforeunit.$labels[$x].$afterunit);
|
||||
elseif($labels[$x] == "MB") return(round($bytes, 2).$beforeunit.$labels[$x].$afterunit);
|
||||
else return(round($bytes, 0).$beforeunit.$labels[$x].$afterunit);
|
||||
$btype = ($is_drive_size === true) ? 1000 : 1024;
|
||||
$labels = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||||
for ($x = 0; $bytes >= $btype && $x < (count($labels) - 1); $bytes /= $btype, $x++); // use 1000 rather than 1024 to simulate HD size not real size
|
||||
if ($labels[$x] == 'TB') {
|
||||
return round($bytes, 3).$beforeunit.$labels[$x].$afterunit;
|
||||
} elseif ($labels[$x] == 'GB') {
|
||||
return round($bytes, 2).$beforeunit.$labels[$x].$afterunit;
|
||||
} elseif ($labels[$x] == 'MB') {
|
||||
return round($bytes, 2).$beforeunit.$labels[$x].$afterunit;
|
||||
} else {
|
||||
return round($bytes, 0).$beforeunit.$labels[$x].$afterunit;
|
||||
}
|
||||
}
|
||||
|
||||
function str_slug($title, $separator = '-', $language = 'en')
|
||||
@@ -34,24 +39,26 @@ if (! function_exists('str_is')) {
|
||||
}
|
||||
}
|
||||
|
||||
function get_brightness($hex) {
|
||||
function get_brightness($hex)
|
||||
{
|
||||
// returns brightness value from 0 to 255
|
||||
// strip off any leading #
|
||||
$hex = str_replace('#', '', $hex);
|
||||
if(strlen($hex) == 3) {
|
||||
// $hex = str_replace('#', '', $hex);
|
||||
$hex = preg_replace("/[^0-9A-Fa-f]/", '', $hex);
|
||||
if (strlen($hex) == 3) {
|
||||
$hex = $hex[0].$hex[0].$hex[1].$hex[1].$hex[2].$hex[2];
|
||||
}
|
||||
|
||||
|
||||
$c_r = hexdec(substr($hex, 0, 2));
|
||||
$c_g = hexdec(substr($hex, 2, 2));
|
||||
$c_b = hexdec(substr($hex, 4, 2));
|
||||
|
||||
|
||||
return (($c_r * 299) + ($c_g * 587) + ($c_b * 114)) / 1000;
|
||||
}
|
||||
|
||||
function title_color($hex)
|
||||
{
|
||||
if(get_brightness($hex) > 130) {
|
||||
if (get_brightness($hex) > 130) {
|
||||
return ' black';
|
||||
} else {
|
||||
return ' white';
|
||||
@@ -62,18 +69,16 @@ function getLinkTargetAttribute()
|
||||
{
|
||||
$target = \App\Setting::fetch('window_target');
|
||||
|
||||
if($target === 'current') {
|
||||
if ($target === 'current') {
|
||||
return '';
|
||||
} else {
|
||||
return ' target="' . $target . '"';
|
||||
return ' target="'.$target.'"';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function className($name)
|
||||
{
|
||||
$name = preg_replace('/\PL/u', '', $name);
|
||||
$name = preg_replace('/[^\p{L}\p{N}]/u', '', $name);
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
use App\User;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
@@ -92,6 +92,7 @@ class LoginController extends Controller
|
||||
{
|
||||
Auth::logout();
|
||||
session(['current_user' => $user]);
|
||||
|
||||
return redirect()->route('dash');
|
||||
}
|
||||
|
||||
@@ -100,6 +101,7 @@ class LoginController extends Controller
|
||||
$user = User::where('autologin', $uuid)->first();
|
||||
Auth::login($user, true);
|
||||
session(['current_user' => $user]);
|
||||
|
||||
return redirect()->route('dash');
|
||||
}
|
||||
|
||||
@@ -122,5 +124,4 @@ class LoginController extends Controller
|
||||
{
|
||||
return Session::get('url.intended') ? Session::get('url.intended') : $this->redirectTo;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\User;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use App\User;
|
||||
use Illuminate\Foundation\Auth\RegistersUsers;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class RegisterController extends Controller
|
||||
{
|
||||
|
||||
@@ -2,12 +2,11 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\User;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
@@ -22,7 +21,6 @@ class Controller extends BaseController
|
||||
//print_r($this->user);
|
||||
return $next($request);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public function user()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
|
||||
class HomeController extends Controller
|
||||
{
|
||||
@@ -13,15 +13,16 @@ class HomeController extends Controller
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the application dashboard.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function index()
|
||||
public function index(): RedirectResponse
|
||||
{
|
||||
return redirect()->route('dash');
|
||||
}
|
||||
|
||||
@@ -2,31 +2,36 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Artisan;
|
||||
use App\Application;
|
||||
use App\Item;
|
||||
use App\Setting;
|
||||
use App\User;
|
||||
use GrahamCampbell\GitHub\Facades\GitHub;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\SupportedApps;
|
||||
use App\Jobs\ProcessApps;
|
||||
use App\Search;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use App\User;
|
||||
use Artisan;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use GuzzleHttp\Exception\ServerException;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
|
||||
class ItemController extends Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware('allowed');
|
||||
}
|
||||
/**
|
||||
|
||||
/**
|
||||
* Display a listing of the resource on the dashboard.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return View
|
||||
*/
|
||||
public function dash()
|
||||
public function dash(): View
|
||||
{
|
||||
$data['apps'] = Item::whereHas('parents', function ($query) {
|
||||
$query->where('id', 0);
|
||||
@@ -41,15 +46,15 @@ class ItemController extends Controller
|
||||
return view('welcome', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Set order on the dashboard.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return void
|
||||
*/
|
||||
public function setOrder(Request $request)
|
||||
{
|
||||
$order = array_filter($request->input('order'));
|
||||
foreach($order as $o => $id) {
|
||||
foreach ($order as $o => $id) {
|
||||
$item = Item::find($id);
|
||||
$item->order = $o;
|
||||
$item->save();
|
||||
@@ -59,136 +64,222 @@ class ItemController extends Controller
|
||||
/**
|
||||
* Pin item on the dashboard.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param $id
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function pin($id)
|
||||
public function pin($id): RedirectResponse
|
||||
{
|
||||
$item = Item::findOrFail($id);
|
||||
$item->pinned = true;
|
||||
$item->save();
|
||||
$route = route('dash', []);
|
||||
|
||||
return redirect($route);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Unpin item on the dashboard.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param $id
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function unpin($id)
|
||||
public function unpin($id): RedirectResponse
|
||||
{
|
||||
$item = Item::findOrFail($id);
|
||||
$item->pinned = false;
|
||||
$item->save();
|
||||
$route = route('dash', []);
|
||||
|
||||
return redirect($route);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Unpin item on the dashboard.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return RedirectResponse|View
|
||||
*/
|
||||
public function pinToggle($id, $ajax=false, $tag=false)
|
||||
public function pinToggle($id, $ajax = false, $tag = false)
|
||||
{
|
||||
$item = Item::findOrFail($id);
|
||||
$new = ((bool)$item->pinned === true) ? false : true;
|
||||
$new = !(((bool)$item->pinned === true));
|
||||
$item->pinned = $new;
|
||||
$item->save();
|
||||
if($ajax) {
|
||||
if(is_numeric($tag) && $tag > 0) {
|
||||
if ($ajax) {
|
||||
if (is_numeric($tag) && $tag > 0) {
|
||||
$item = Item::whereId($tag)->first();
|
||||
$data['apps'] = $item->children()->pinned()->orderBy('order', 'asc')->get();
|
||||
} else {
|
||||
$data['apps'] = Item::pinned()->orderBy('order', 'asc')->get();
|
||||
}
|
||||
$data['ajax'] = true;
|
||||
|
||||
return view('sortable', $data);
|
||||
} else {
|
||||
$route = route('dash', []);
|
||||
|
||||
return redirect($route);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$trash = (bool)$request->input('trash');
|
||||
$trash = (bool) $request->input('trash');
|
||||
|
||||
$data['apps'] = Item::ofType('item')->orderBy('title', 'asc')->get();
|
||||
$data['trash'] = Item::ofType('item')->onlyTrashed()->get();
|
||||
if($trash) {
|
||||
if ($trash) {
|
||||
return view('items.trash', $data);
|
||||
} else {
|
||||
return view('items.list', $data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return View
|
||||
*/
|
||||
public function create()
|
||||
public function create(): View
|
||||
{
|
||||
//
|
||||
$data['tags'] = Item::ofType('tag')->orderBy('title', 'asc')->pluck('title', 'id');
|
||||
$data['tags']->prepend(__('app.dashboard'), 0);
|
||||
$data['current_tags'] = collect([0 => __('app.dashboard')]);
|
||||
return view('items.create', $data);
|
||||
$data['current_tags'] = '0';
|
||||
|
||||
return view('items.create', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param int $id
|
||||
* @return View
|
||||
*/
|
||||
public function store(Request $request)
|
||||
public function edit(int $id): View
|
||||
{
|
||||
//
|
||||
// Get the item
|
||||
$item = Item::find($id);
|
||||
if ($item->appid === null && $item->class !== null) { // old apps wont have an app id so set it
|
||||
$app = Application::where('class', $item->class)->first();
|
||||
if ($app) {
|
||||
$item->appid = $app->appid;
|
||||
}
|
||||
}
|
||||
$data['item'] = $item;
|
||||
$data['tags'] = Item::ofType('tag')->orderBy('title', 'asc')->pluck('title', 'id');
|
||||
$data['tags']->prepend(__('app.dashboard'), 0);
|
||||
$data['current_tags'] = $data['item']->tags();
|
||||
//$data['current_tags'] = $data['item']->parent;
|
||||
//die(print_r($data['current_tags']));
|
||||
// show the edit form and pass the nerd
|
||||
return view('items.edit', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param $id
|
||||
* @return void
|
||||
*/
|
||||
public function storelogic(Request $request, $id = null)
|
||||
{
|
||||
$application = Application::single($request->input('appid'));
|
||||
$validatedData = $request->validate([
|
||||
'title' => 'required|max:255',
|
||||
'url' => 'required',
|
||||
]);
|
||||
|
||||
if($request->hasFile('file')) {
|
||||
if ($request->hasFile('file')) {
|
||||
$path = $request->file('file')->store('icons');
|
||||
$request->merge([
|
||||
'icon' => $path
|
||||
'icon' => $path,
|
||||
]);
|
||||
} elseif (strpos($request->input('icon'), 'http') === 0) {
|
||||
$options=array(
|
||||
"ssl"=>array(
|
||||
"verify_peer"=>false,
|
||||
"verify_peer_name"=>false,
|
||||
),
|
||||
);
|
||||
$contents = file_get_contents($request->input('icon'), false, stream_context_create($options));
|
||||
|
||||
if ($application) {
|
||||
$icon = $application->icon;
|
||||
} else {
|
||||
$file = $request->input('icon');
|
||||
$path_parts = pathinfo($file);
|
||||
$icon = md5($contents);
|
||||
$icon .= '.'.$path_parts['extension'];
|
||||
}
|
||||
$path = 'icons/'.$icon;
|
||||
|
||||
// Private apps could have here duplicated icons folder
|
||||
if (strpos($path, 'icons/icons/') !== false) {
|
||||
$path = str_replace('icons/icons/','icons/',$path);
|
||||
}
|
||||
if(! Storage::disk('public')->exists($path)) {
|
||||
Storage::disk('public')->put($path, $contents);
|
||||
}
|
||||
$request->merge([
|
||||
'icon' => $path,
|
||||
]);
|
||||
}
|
||||
|
||||
$config = Item::checkConfig($request->input('config'));
|
||||
|
||||
// Don't overwrite the stored password if it wasn't submitted when updating the item
|
||||
if ($id !== null && strpos($config, '"password":null') !== false) {
|
||||
$storedItem = Item::find($id);
|
||||
$storedConfigObject = json_decode($storedItem->getAttribute('description'));
|
||||
|
||||
$configObject = json_decode($config);
|
||||
$configObject->password = $storedConfigObject->password;
|
||||
|
||||
$config = json_encode($configObject);
|
||||
}
|
||||
|
||||
$current_user = User::currentUser();
|
||||
$request->merge([
|
||||
'description' => $config,
|
||||
'user_id' => $current_user->id
|
||||
'user_id' => $current_user->getId(),
|
||||
]);
|
||||
|
||||
if($request->input('class') === 'null') {
|
||||
if ($request->input('appid') === 'null') {
|
||||
$request->merge([
|
||||
'class' => null,
|
||||
]);
|
||||
} else {
|
||||
$request->merge([
|
||||
'class' => Application::classFromName($application->name),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
//die(print_r($request->input('config')));
|
||||
|
||||
$item = Item::create($request->all());
|
||||
|
||||
//Search::storeSearchProvider($request->input('class'), $item);
|
||||
if ($id === null) {
|
||||
$item = Item::create($request->all());
|
||||
} else {
|
||||
$item = Item::find($id);
|
||||
$item->update($request->all());
|
||||
}
|
||||
|
||||
$item->parents()->sync($request->tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
$this->storelogic($request);
|
||||
|
||||
$route = route('dash', []);
|
||||
|
||||
return redirect($route)
|
||||
->with('success', __('app.alert.success.item_created'));
|
||||
}
|
||||
@@ -196,91 +287,42 @@ class ItemController extends Controller
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param int $id
|
||||
* @return void
|
||||
*/
|
||||
public function show($id)
|
||||
public function show(int $id): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
// Get the item
|
||||
$data['item'] = Item::find($id);
|
||||
$data['tags'] = Item::ofType('tag')->orderBy('title', 'asc')->pluck('title', 'id');
|
||||
$data['tags']->prepend(__('app.dashboard'), 0);
|
||||
$data['current_tags'] = $data['item']->tags();
|
||||
//$data['current_tags'] = $data['item']->parent;
|
||||
//die(print_r($data['current_tags']));
|
||||
// show the edit form and pass the nerd
|
||||
return view('items.edit', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
public function update(Request $request, int $id): RedirectResponse
|
||||
{
|
||||
$validatedData = $request->validate([
|
||||
'title' => 'required|max:255',
|
||||
'url' => 'required',
|
||||
]);
|
||||
//die(print_r($request->all()));
|
||||
if($request->hasFile('file')) {
|
||||
$path = $request->file('file')->store('icons');
|
||||
$request->merge([
|
||||
'icon' => $path
|
||||
]);
|
||||
}
|
||||
|
||||
$config = Item::checkConfig($request->input('config'));
|
||||
$current_user = User::currentUser();
|
||||
$request->merge([
|
||||
'description' => $config,
|
||||
'user_id' => $current_user->id
|
||||
]);
|
||||
|
||||
if($request->input('class') === 'null') {
|
||||
$request->merge([
|
||||
'class' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
$item = Item::find($id);
|
||||
$item->update($request->all());
|
||||
|
||||
//Search::storeSearchProvider($request->input('class'), $item);
|
||||
|
||||
$item->parents()->sync($request->tags);
|
||||
|
||||
$this->storelogic($request, $id);
|
||||
$route = route('dash', []);
|
||||
|
||||
return redirect($route)
|
||||
->with('success',__('app.alert.success.item_updated'));
|
||||
->with('success', __('app.alert.success.item_updated'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function destroy(Request $request, $id)
|
||||
public function destroy(Request $request, int $id): RedirectResponse
|
||||
{
|
||||
//
|
||||
$force = (bool)$request->input('force');
|
||||
if($force) {
|
||||
$force = (bool) $request->input('force');
|
||||
if ($force) {
|
||||
Item::withTrashed()
|
||||
->where('id', $id)
|
||||
->forceDelete();
|
||||
@@ -289,57 +331,72 @@ class ItemController extends Controller
|
||||
}
|
||||
|
||||
$route = route('items.index', []);
|
||||
return redirect($route)
|
||||
->with('success',__('app.alert.success.item_deleted'));
|
||||
|
||||
return redirect($route)
|
||||
->with('success', __('app.alert.success.item_deleted'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the specified resource from soft deletion.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param int $id
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function restore($id)
|
||||
public function restore(int $id): RedirectResponse
|
||||
{
|
||||
//
|
||||
Item::withTrashed()
|
||||
->where('id', $id)
|
||||
->restore();
|
||||
|
||||
->restore();
|
||||
|
||||
$route = route('items.index', []);
|
||||
|
||||
return redirect($route)
|
||||
->with('success',__('app.alert.success.item_restored'));
|
||||
->with('success', __('app.alert.success.item_restored'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return details for supported apps
|
||||
*
|
||||
* @return Json
|
||||
* @param Request $request
|
||||
* @return string|null
|
||||
*/
|
||||
public function appload(Request $request)
|
||||
public function appload(Request $request): ?string
|
||||
{
|
||||
$output = [];
|
||||
$appname = $request->input('app');
|
||||
//die($appname);
|
||||
$appid = $request->input('app');
|
||||
|
||||
$app_details = Application::where('name', $appname)->firstOrFail();
|
||||
$appclass = $app_details->class();
|
||||
$app = new $appclass;
|
||||
|
||||
// basic details
|
||||
$output['icon'] = $app_details->icon();
|
||||
$output['name'] = $app_details->name;
|
||||
$output['iconview'] = $app_details->iconView();
|
||||
$output['colour'] = $app_details->defaultColour();
|
||||
$output['class'] = $appclass;
|
||||
|
||||
// live details
|
||||
if($app instanceof \App\EnhancedApps) {
|
||||
$output['config'] = className($app_details->name).'.config';
|
||||
} else {
|
||||
$output['config'] = null;
|
||||
if ($appid === 'null') {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
$output['config'] = null;
|
||||
$output['custom'] = null;
|
||||
|
||||
$app = Application::single($appid);
|
||||
$output = (array) $app;
|
||||
|
||||
$appdetails = Application::getApp($appid);
|
||||
|
||||
if ((bool) $app->enhanced === true) {
|
||||
// if(!isset($app->config)) { // class based config
|
||||
$output['custom'] = className($appdetails->name).'.config';
|
||||
// }
|
||||
}
|
||||
|
||||
$output['colour'] = ($app->tile_background == 'light') ? '#fafbfc' : '#161b1f';
|
||||
|
||||
if(strpos($app->icon, '://') !== false) {
|
||||
$output['iconview'] = $app->icon;
|
||||
} elseif(strpos($app->icon, 'icons/') !== false) {
|
||||
// Private apps have the icon locally
|
||||
$output['iconview'] = URL::to('/').'/storage/'.$app->icon;
|
||||
$output['icon'] = str_replace('icons/', '', $output['icon']);
|
||||
} else {
|
||||
$output['iconview'] = config('app.appsource').'icons/'.$app->icon;
|
||||
}
|
||||
|
||||
|
||||
return json_encode($output);
|
||||
}
|
||||
|
||||
@@ -347,39 +404,80 @@ class ItemController extends Controller
|
||||
{
|
||||
$data = $request->input('data');
|
||||
//$url = $data[array_search('url', array_column($data, 'name'))]['value'];
|
||||
|
||||
$app = $data['type'];
|
||||
$single = Application::single($data['type']);
|
||||
$app = $single->class;
|
||||
|
||||
// If password is not resubmitted fill it from the database when in edit mode
|
||||
if (array_key_exists('password', $data) &&
|
||||
$data['password'] === null &&
|
||||
array_key_exists('id', $data)
|
||||
) {
|
||||
$item = Item::find($data['id']);
|
||||
if ($item) {
|
||||
$itemConfig = $item->getConfig();
|
||||
$data['password'] = $itemConfig->password;
|
||||
}
|
||||
}
|
||||
|
||||
$app_details = new $app();
|
||||
$app_details->config = (object)$data;
|
||||
$app_details->config = (object) $data;
|
||||
$app_details->test();
|
||||
}
|
||||
|
||||
public function execute($url, $attrs = [], $overridevars = false)
|
||||
{
|
||||
$res = null;
|
||||
|
||||
$vars = ($overridevars !== false) ?
|
||||
$overridevars : [
|
||||
'http_errors' => false,
|
||||
'timeout' => 15,
|
||||
'connect_timeout' => 15,
|
||||
'verify' => false,
|
||||
];
|
||||
|
||||
$client = new Client($vars);
|
||||
|
||||
$method = 'GET';
|
||||
|
||||
try {
|
||||
return $client->request($method, $url, $attrs);
|
||||
} catch (ConnectException $e) {
|
||||
Log::error('Connection refused');
|
||||
Log::debug($e->getMessage());
|
||||
} catch (ServerException $e) {
|
||||
Log::debug($e->getMessage());
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function websitelookup($url)
|
||||
{
|
||||
$url = base64_decode($url);
|
||||
$data = $this->execute($url);
|
||||
|
||||
return $data->getBody();
|
||||
}
|
||||
|
||||
public function getStats($id)
|
||||
{
|
||||
$item = Item::find($id);
|
||||
|
||||
$config = $item->getconfig();
|
||||
if(isset($item->class)) {
|
||||
if (isset($item->class)) {
|
||||
$application = new $item->class;
|
||||
$application->config = $config;
|
||||
echo $application->livestats();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function checkAppList()
|
||||
{
|
||||
ProcessApps::dispatch();
|
||||
$route = route('items.index');
|
||||
|
||||
return redirect($route)
|
||||
->with('success', __('app.alert.success.updating'));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Search;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class SearchController extends Controller
|
||||
{
|
||||
@@ -15,9 +14,9 @@ class SearchController extends Controller
|
||||
|
||||
$provider = Search::providerDetails($requestprovider);
|
||||
|
||||
if($provider->type == 'standard') {
|
||||
if ($provider->type == 'standard') {
|
||||
return redirect($provider->url.'?'.$provider->query.'='.urlencode($query));
|
||||
} elseif($provider->type == 'external') {
|
||||
} elseif ($provider->type == 'external') {
|
||||
$class = new $provider->class;
|
||||
//print_r($provider);
|
||||
return $class->getResults($query, $provider);
|
||||
|
||||
@@ -2,24 +2,24 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Setting;
|
||||
use App\SettingGroup;
|
||||
use App\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class SettingsController extends Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware('allowed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function index()
|
||||
public function index(): View
|
||||
{
|
||||
$settings = SettingGroup::with([
|
||||
'settings',
|
||||
@@ -33,22 +33,25 @@ class SettingsController extends Controller
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @return RedirectResponse|View
|
||||
*/
|
||||
public function edit($id)
|
||||
public function edit(int $id)
|
||||
{
|
||||
$setting = Setting::find($id);
|
||||
//die("s: ".$setting->label);
|
||||
|
||||
if((bool)$setting->system === true) return abort(404);
|
||||
if ((bool) $setting->system === true) {
|
||||
return abort(404);
|
||||
}
|
||||
|
||||
if (!is_null($setting)) {
|
||||
if (! is_null($setting)) {
|
||||
return view('settings.edit')->with([
|
||||
'setting' => $setting,
|
||||
]);
|
||||
} else {
|
||||
$route = route('settings.list', []);
|
||||
return redirect($route)
|
||||
|
||||
return redirect($route)
|
||||
->with([
|
||||
'error' => __('app.alert.error.not_exist'),
|
||||
]);
|
||||
@@ -56,72 +59,71 @@ class SettingsController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
public function update(Request $request, int $id): RedirectResponse
|
||||
{
|
||||
$setting = Setting::find($id);
|
||||
$user = $this->user();
|
||||
|
||||
if (!is_null($setting)) {
|
||||
if (! is_null($setting)) {
|
||||
$data = Setting::getInput($request);
|
||||
|
||||
$setting_value = null;
|
||||
|
||||
if ($setting->type == 'image') {
|
||||
|
||||
|
||||
if($request->hasFile('value')) {
|
||||
if ($request->hasFile('value')) {
|
||||
$path = $request->file('value')->store('backgrounds');
|
||||
$setting_value = $path;
|
||||
}
|
||||
|
||||
} else {
|
||||
$setting_value = $data->value;
|
||||
}
|
||||
|
||||
$user->settings()->detach($setting->id);
|
||||
$user->settings()->save($setting, ['uservalue' => $setting_value]);
|
||||
|
||||
|
||||
$route = route('settings.index', []);
|
||||
return redirect($route)
|
||||
|
||||
return redirect($route)
|
||||
->with([
|
||||
'success' => __('app.alert.success.setting_updated'),
|
||||
]);
|
||||
} else {
|
||||
$route = route('settings.index', []);
|
||||
return redirect($route)
|
||||
|
||||
return redirect($route)
|
||||
->with([
|
||||
'error' => __('app.alert.error.not_exist'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function clear($id)
|
||||
public function clear(int $id): RedirectResponse
|
||||
{
|
||||
$user = $this->user();
|
||||
$setting = Setting::find($id);
|
||||
if((bool)$setting->system !== true) {
|
||||
if ((bool) $setting->system !== true) {
|
||||
$user->settings()->detach($setting->id);
|
||||
$user->settings()->save($setting, ['uservalue' => '']);
|
||||
}
|
||||
$route = route('settings.index', []);
|
||||
return redirect($route)
|
||||
|
||||
return redirect($route)
|
||||
->with([
|
||||
'success' => __('app.alert.success.setting_updated'),
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
public function search(Request $request)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Item;
|
||||
use App\User;
|
||||
use DB;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
|
||||
class TagController extends Controller
|
||||
{
|
||||
@@ -13,18 +16,19 @@ class TagController extends Controller
|
||||
{
|
||||
$this->middleware('allowed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$trash = (bool)$request->input('trash');
|
||||
$trash = (bool) $request->input('trash');
|
||||
|
||||
$data['apps'] = Item::ofType('tag')->where('id', '>', 0)->orderBy('title', 'asc')->get();
|
||||
$data['trash'] = Item::ofType('tag')->where('id', '>', 0)->onlyTrashed()->get();
|
||||
if($trash) {
|
||||
if ($trash) {
|
||||
return view('tags.trash', $data);
|
||||
} else {
|
||||
return view('tags.list', $data);
|
||||
@@ -34,30 +38,31 @@ class TagController extends Controller
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$data = [];
|
||||
|
||||
return view('tags.create', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param Request $request
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
$validatedData = $request->validate([
|
||||
'title' => 'required|max:255',
|
||||
]);
|
||||
|
||||
if($request->hasFile('file')) {
|
||||
if ($request->hasFile('file')) {
|
||||
$path = $request->file('file')->store('icons');
|
||||
$request->merge([
|
||||
'icon' => $path
|
||||
'icon' => $path,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -69,12 +74,13 @@ class TagController extends Controller
|
||||
$request->merge([
|
||||
'type' => '1',
|
||||
'url' => $slug,
|
||||
'user_id' => $current_user->id
|
||||
'user_id' => $current_user->getId(),
|
||||
]);
|
||||
//die(print_r($request->all()));
|
||||
Item::create($request->all());
|
||||
|
||||
$route = route('dash', []);
|
||||
|
||||
return redirect($route)
|
||||
->with('success', __('app.alert.success.tag_created'));
|
||||
}
|
||||
@@ -82,121 +88,132 @@ class TagController extends Controller
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param $slug
|
||||
* @return View
|
||||
*/
|
||||
public function show($slug)
|
||||
public function show($slug): View
|
||||
{
|
||||
$item = Item::whereUrl($slug)->first();
|
||||
//print_r($item);
|
||||
$data['apps'] = $item->children()->pinned()->orderBy('order', 'asc')->get();
|
||||
$data['tag'] = $item->id;
|
||||
$data['all_apps'] = $item->children;
|
||||
|
||||
return view('welcome', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param int $id
|
||||
* @return View
|
||||
*/
|
||||
public function edit($id)
|
||||
public function edit(int $id): View
|
||||
{
|
||||
// Get the item
|
||||
$item = Item::find($id);
|
||||
|
||||
// show the edit form and pass the nerd
|
||||
return view('tags.edit')
|
||||
->with('item', $item);
|
||||
->with('item', $item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
public function update(Request $request, int $id): RedirectResponse
|
||||
{
|
||||
$validatedData = $request->validate([
|
||||
'title' => 'required|max:255',
|
||||
]);
|
||||
|
||||
if($request->hasFile('file')) {
|
||||
if ($request->hasFile('file')) {
|
||||
$path = $request->file('file')->store('icons');
|
||||
$request->merge([
|
||||
'icon' => $path
|
||||
'icon' => $path,
|
||||
]);
|
||||
}
|
||||
|
||||
$slug = str_slug($request->title, '-');
|
||||
// set item type to tag
|
||||
$request->merge([
|
||||
'url' => $slug
|
||||
'url' => $slug,
|
||||
]);
|
||||
|
||||
Item::find($id)->update($request->all());
|
||||
|
||||
$route = route('dash', []);
|
||||
|
||||
return redirect($route)
|
||||
->with('success',__('app.alert.success.tag_updated'));
|
||||
->with('success', __('app.alert.success.tag_updated'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param int $id
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function destroy(Request $request, $id)
|
||||
public function destroy(Request $request, int $id): RedirectResponse
|
||||
{
|
||||
//
|
||||
$force = (bool)$request->input('force');
|
||||
if($force) {
|
||||
$force = (bool) $request->input('force');
|
||||
if ($force) {
|
||||
Item::withTrashed()
|
||||
->where('id', $id)
|
||||
->forceDelete();
|
||||
} else {
|
||||
Item::find($id)->delete();
|
||||
}
|
||||
|
||||
|
||||
$route = route('tags.index', []);
|
||||
|
||||
return redirect($route)
|
||||
->with('success',__('app.alert.success.item_deleted'));
|
||||
->with('success', __('app.alert.success.item_deleted'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the specified resource from soft deletion.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param int $id
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function restore($id)
|
||||
public function restore(int $id): RedirectResponse
|
||||
{
|
||||
//
|
||||
Item::withTrashed()
|
||||
->where('id', $id)
|
||||
->restore();
|
||||
->restore();
|
||||
$route = route('tags.index', []);
|
||||
|
||||
return redirect($route)
|
||||
->with('success',__('app.alert.success.item_restored'));
|
||||
->with('success', __('app.alert.success.item_restored'));
|
||||
}
|
||||
|
||||
public function add($tag, $item)
|
||||
/**
|
||||
* Add item to tag
|
||||
*
|
||||
* @param $tag
|
||||
* @param $item
|
||||
* @return int 1|0
|
||||
*/
|
||||
public function add($tag, $item): int
|
||||
{
|
||||
$output = 0;
|
||||
$tag = Item::find($tag);
|
||||
$item = Item::find($item);
|
||||
if($tag && $item) {
|
||||
if ($tag && $item) {
|
||||
// only add items, not cats
|
||||
if((int)$item->type === 0) {
|
||||
if ((int) $item->type === 0) {
|
||||
$tag->children()->attach($item);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,37 +2,42 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\User;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware('allowed')->except(['selectUser']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return View
|
||||
*/
|
||||
public function index()
|
||||
public function index(): View
|
||||
{
|
||||
$data['users'] = User::all();
|
||||
|
||||
return view('users.index', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return View
|
||||
*/
|
||||
public function create()
|
||||
public function create(): View
|
||||
{
|
||||
$data = [];
|
||||
|
||||
return view('users.create', $data);
|
||||
}
|
||||
|
||||
@@ -40,23 +45,23 @@ class UserController extends Controller
|
||||
{
|
||||
Auth::logout();
|
||||
$data['users'] = User::all();
|
||||
return view('userselect', $data);
|
||||
|
||||
return view('userselect', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param Request $request
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
$validatedData = $request->validate([
|
||||
'username' => 'required|max:255|unique:users',
|
||||
'email' => 'required|email',
|
||||
'password' => 'nullable|confirmed',
|
||||
'password_confirmation' => 'nullable'
|
||||
'password_confirmation' => 'nullable',
|
||||
|
||||
]);
|
||||
$user = new User;
|
||||
@@ -65,33 +70,34 @@ class UserController extends Controller
|
||||
$user->public_front = $request->input('public_front');
|
||||
|
||||
$password = $request->input('password');
|
||||
if(!empty($password)) {
|
||||
if (! empty($password)) {
|
||||
$user->password = bcrypt($password);
|
||||
}
|
||||
|
||||
if($request->hasFile('file')) {
|
||||
if ($request->hasFile('file')) {
|
||||
$path = $request->file('file')->store('avatars');
|
||||
$user->avatar = $path;
|
||||
}
|
||||
|
||||
if ((bool)$request->input('autologin_allow') === true) {
|
||||
$user->autologin = (string)Str::uuid();
|
||||
if ((bool) $request->input('autologin_allow') === true) {
|
||||
$user->autologin = (string) Str::uuid();
|
||||
}
|
||||
|
||||
$user->save();
|
||||
|
||||
|
||||
$route = route('dash', []);
|
||||
|
||||
return redirect($route)
|
||||
->with('success',__('app.alert.success.user_updated'));
|
||||
->with('success', __('app.alert.success.user_updated'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param int $id
|
||||
* @return void
|
||||
*/
|
||||
public function show($id)
|
||||
public function show(int $id): void
|
||||
{
|
||||
//
|
||||
}
|
||||
@@ -99,51 +105,51 @@ class UserController extends Controller
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param User $user
|
||||
* @return View
|
||||
*/
|
||||
public function edit(User $user)
|
||||
public function edit(User $user): View
|
||||
{
|
||||
$data['user'] = $user;
|
||||
return view('users.edit', $data);
|
||||
|
||||
return view('users.edit', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param Request $request
|
||||
* @param User $user
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function update(Request $request, User $user)
|
||||
public function update(Request $request, User $user): RedirectResponse
|
||||
{
|
||||
$validatedData = $request->validate([
|
||||
'username' => 'required|max:255|unique:users,username,'.$user->id,
|
||||
'email' => 'required|email',
|
||||
'password' => 'nullable|confirmed',
|
||||
'password_confirmation' => 'nullable'
|
||||
'password_confirmation' => 'nullable',
|
||||
]);
|
||||
//die(print_r($request->all()));
|
||||
//die(print_r($request->all()));
|
||||
|
||||
$user->username = $request->input('username');
|
||||
$user->email = $request->input('email');
|
||||
$user->public_front = $request->input('public_front');
|
||||
|
||||
$password = $request->input('password');
|
||||
if(!empty($password)) {
|
||||
if (! empty($password)) {
|
||||
$user->password = bcrypt($password);
|
||||
} elseif($password == 'null') {
|
||||
} elseif ($password == 'null') {
|
||||
$user->password = null;
|
||||
}
|
||||
|
||||
if($request->hasFile('file')) {
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
$path = $request->file('file')->store('avatars');
|
||||
$user->avatar = $path;
|
||||
}
|
||||
|
||||
if ((bool)$request->input('autologin_allow') === true) {
|
||||
$user->autologin = (is_null($user->autologin)) ? (string)Str::uuid() : $user->autologin;
|
||||
if ((bool) $request->input('autologin_allow') === true) {
|
||||
$user->autologin = (is_null($user->autologin)) ? (string) Str::uuid() : $user->autologin;
|
||||
} else {
|
||||
$user->autologin = null;
|
||||
}
|
||||
@@ -151,25 +157,25 @@ class UserController extends Controller
|
||||
$user->save();
|
||||
|
||||
$route = route('dash', []);
|
||||
return redirect($route)
|
||||
->with('success',__('app.alert.success.user_updated'));
|
||||
|
||||
return redirect($route)
|
||||
->with('success', __('app.alert.success.user_updated'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param User $user
|
||||
* @return RedirectResponse | void
|
||||
*/
|
||||
public function destroy(User $user)
|
||||
public function destroy(User $user): RedirectResponse
|
||||
{
|
||||
if($user->id !== 1) {
|
||||
if ($user->id !== 1) {
|
||||
$user->delete();
|
||||
$route = route('dash', []);
|
||||
return redirect($route)
|
||||
->with('success',__('app.alert.success.user_deleted'));
|
||||
|
||||
return redirect($route)
|
||||
->with('success', __('app.alert.success.user_deleted'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\User;
|
||||
use Closure;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\User;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Session;
|
||||
|
||||
@@ -22,27 +22,37 @@ class CheckAllowed
|
||||
$route = Route::currentRouteName();
|
||||
$current_user = User::currentUser();
|
||||
|
||||
if(str_is('users*', $route)) {
|
||||
if($current_user->id !== 1) {
|
||||
// Non admin users can't access users management
|
||||
if (str_is('users*', $route)) {
|
||||
if ($current_user->getId() !== 1) {
|
||||
return redirect()->route('dash');
|
||||
}
|
||||
}
|
||||
|
||||
if($route == 'dash') {
|
||||
// Public access to frontpage
|
||||
if ($route == 'dash') {
|
||||
//print_r(User::all());
|
||||
//die("here".var_dump($current_user->password));
|
||||
if((bool)$current_user->public_front === true) return $next($request);
|
||||
if ((bool)$current_user->public_front === true) {
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
||||
if(empty($current_user->password)) return $next($request);
|
||||
// Continue with passwordless user
|
||||
if (empty($current_user->password)) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
// Check if user is logged in as $current_user
|
||||
if (Auth::check()) {
|
||||
$loggedin_user = Auth::user();
|
||||
if($loggedin_user->id === $current_user->id) return $next($request);
|
||||
if ($loggedin_user->id === $current_user->getId()) {
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
||||
return Auth::authenticate();
|
||||
|
||||
// Redirect to login
|
||||
Auth::authenticate();
|
||||
return redirect()->route('user.select');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Fideloper\Proxy\TrustProxies as Middleware;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class TrustProxies extends Middleware
|
||||
{
|
||||
@@ -12,7 +12,7 @@ class TrustProxies extends Middleware
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $proxies = ['192.168.0.0/16', '172.16.0.0/12','10.0.0.0/8', '127.0.0.1'];
|
||||
protected $proxies = ['192.168.0.0/16', '172.16.0.0/12', '10.0.0.0/8', '127.0.0.1'];
|
||||
|
||||
/**
|
||||
* The current proxy header mappings.
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
|
||||
use Symfony\Component\HttpFoundation\Cookie;
|
||||
|
||||
class VerifyCsrfToken extends Middleware
|
||||
{
|
||||
@@ -20,39 +19,4 @@ class VerifyCsrfToken extends Middleware
|
||||
//'get_stats'
|
||||
];
|
||||
|
||||
/**
|
||||
* Add the CSRF token to the response cookies.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Symfony\Component\HttpFoundation\Response $response
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
protected function addCookieToResponse($request, $response)
|
||||
{
|
||||
$config = config('session');
|
||||
|
||||
if ($response instanceof Responsable) {
|
||||
$response = $response->toResponse($request);
|
||||
}
|
||||
|
||||
$response->headers->setCookie(
|
||||
new Cookie(
|
||||
'HEIMDALL-XSRF-TOKEN', $request->session()->token(), $this->availableAt(60 * $config['lifetime']),
|
||||
$config['path'], $config['domain'], $config['secure'], false, false, $config['same_site'] ?? null
|
||||
)
|
||||
);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the cookie contents should be serialized.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function serialized()
|
||||
{
|
||||
return EncryptCookies::serialized('HEIMDALL-XSRF-TOKEN');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
121
app/Item.php
121
app/Item.php
@@ -2,13 +2,10 @@
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Symfony\Component\ClassLoader\ClassMapGenerator;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use App\User;
|
||||
use App\ItemTag;
|
||||
use App\Application;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\ClassLoader\ClassMapGenerator;
|
||||
|
||||
class Item extends Model
|
||||
{
|
||||
@@ -20,8 +17,8 @@ class Item extends Model
|
||||
|
||||
static::addGlobalScope('user_id', function (Builder $builder) {
|
||||
$current_user = User::currentUser();
|
||||
if($current_user) {
|
||||
$builder->where('user_id', $current_user->id)->orWhere('user_id', 0);
|
||||
if ($current_user) {
|
||||
$builder->where('user_id', $current_user->getId())->orWhere('user_id', 0);
|
||||
} else {
|
||||
$builder->where('user_id', 0);
|
||||
}
|
||||
@@ -30,15 +27,10 @@ class Item extends Model
|
||||
|
||||
//
|
||||
protected $fillable = [
|
||||
'title', 'url', 'colour', 'icon', 'description', 'pinned', 'order', 'type', 'class', 'user_id'
|
||||
'title', 'url', 'colour', 'icon', 'appdescription', 'description', 'pinned', 'order', 'type', 'class', 'user_id', 'tag_id', 'appid',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be mutated to dates.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $dates = ['deleted_at'];
|
||||
|
||||
|
||||
/**
|
||||
* Scope a query to only include pinned items.
|
||||
@@ -53,46 +45,48 @@ class Item extends Model
|
||||
|
||||
public static function checkConfig($config)
|
||||
{
|
||||
if(empty($config)) {
|
||||
// die(print_r($config));
|
||||
if (empty($config)) {
|
||||
$config = null;
|
||||
} else {
|
||||
$config = json_encode($config);
|
||||
}
|
||||
|
||||
return $config;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function tags()
|
||||
{
|
||||
$id = $this->id;
|
||||
$tags = ItemTag::select('tag_id')->where('item_id', $id)->pluck('tag_id')->toArray();
|
||||
$tagdetails = Item::select('id', 'title', 'url', 'pinned')->whereIn('id', $tags)->get();
|
||||
$tagdetails = self::select('id', 'title', 'url', 'pinned')->whereIn('id', $tags)->get();
|
||||
//print_r($tags);
|
||||
if(in_array(0, $tags)) {
|
||||
$details = new Item([
|
||||
"id" => 0,
|
||||
"title" => __('app.dashboard'),
|
||||
"url" => '',
|
||||
"pinned" => 0
|
||||
if (in_array(0, $tags)) {
|
||||
$details = new self([
|
||||
'id' => 0,
|
||||
'title' => __('app.dashboard'),
|
||||
'url' => '',
|
||||
'pinned' => 0,
|
||||
]);
|
||||
$tagdetails->prepend($details);
|
||||
}
|
||||
|
||||
return $tagdetails;
|
||||
}
|
||||
|
||||
public function parents()
|
||||
{
|
||||
return $this->belongsToMany('App\Item', 'item_tag', 'item_id', 'tag_id');
|
||||
return $this->belongsToMany(\App\Item::class, 'item_tag', 'item_id', 'tag_id');
|
||||
}
|
||||
|
||||
public function children()
|
||||
{
|
||||
return $this->belongsToMany('App\Item', 'item_tag', 'tag_id', 'item_id');
|
||||
return $this->belongsToMany(\App\Item::class, 'item_tag', 'tag_id', 'item_id');
|
||||
}
|
||||
|
||||
public function getLinkAttribute()
|
||||
{
|
||||
if((int)$this->type === 1) {
|
||||
if ((int) $this->type === 1) {
|
||||
return url('tag/'.$this->url);
|
||||
} else {
|
||||
return $this->url;
|
||||
@@ -101,7 +95,7 @@ class Item extends Model
|
||||
|
||||
public function getDroppableAttribute()
|
||||
{
|
||||
if((int)$this->type === 1) {
|
||||
if ((int) $this->type === 1) {
|
||||
return ' droppable';
|
||||
} else {
|
||||
return '';
|
||||
@@ -112,24 +106,25 @@ class Item extends Model
|
||||
{
|
||||
$target = Setting::fetch('window_target');
|
||||
|
||||
if((int)$this->type === 1 || $target === 'current') {
|
||||
if ((int) $this->type === 1 || $target === 'current') {
|
||||
return '';
|
||||
} else {
|
||||
return ' target="' . $target . '"';
|
||||
return ' target="'.$target.'"';
|
||||
}
|
||||
}
|
||||
|
||||
public function getLinkIconAttribute()
|
||||
{
|
||||
if((int)$this->type === 1) {
|
||||
if ((int) $this->type === 1) {
|
||||
return 'fa-tag';
|
||||
} else {
|
||||
return 'fa-arrow-alt-to-right';
|
||||
}
|
||||
}
|
||||
|
||||
public function getLinkTypeAttribute()
|
||||
{
|
||||
if((int)$this->type === 1) {
|
||||
if ((int) $this->type === 1) {
|
||||
return 'tags';
|
||||
} else {
|
||||
return 'items';
|
||||
@@ -140,13 +135,13 @@ class Item extends Model
|
||||
{
|
||||
$explode = explode('\\', $class);
|
||||
$name = end($explode);
|
||||
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
public function scopeOfType($query, $type)
|
||||
{
|
||||
switch($type) {
|
||||
switch ($type) {
|
||||
case 'item':
|
||||
$typeid = 0;
|
||||
break;
|
||||
@@ -160,87 +155,95 @@ class Item extends Model
|
||||
|
||||
public function enhanced()
|
||||
{
|
||||
if(isset($this->class) && !empty($this->class)) {
|
||||
/*if(isset($this->class) && !empty($this->class)) {
|
||||
$app = new $this->class;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return (bool)($app instanceof \App\EnhancedApps);
|
||||
return (bool)($app instanceof \App\EnhancedApps);*/
|
||||
return $this->description !== null;
|
||||
}
|
||||
|
||||
public static function isEnhanced($class)
|
||||
{
|
||||
if($class === null || $class === 'null') return false;
|
||||
if (!class_exists($class, false) || $class === null || $class === 'null') {
|
||||
return false;
|
||||
}
|
||||
$app = new $class;
|
||||
return (bool)($app instanceof \App\EnhancedApps);
|
||||
|
||||
return (bool) ($app instanceof \App\EnhancedApps);
|
||||
}
|
||||
|
||||
public static function isSearchProvider($class)
|
||||
{
|
||||
if (!class_exists($class, false) || $class === null || $class === 'null') {
|
||||
return false;
|
||||
}
|
||||
$app = new $class;
|
||||
return ((bool)($app instanceof \App\SearchInterface)) ? $app : false;
|
||||
|
||||
return ((bool) ($app instanceof \App\SearchInterface)) ? $app : false;
|
||||
}
|
||||
|
||||
public function enabled()
|
||||
{
|
||||
if($this->enhanced()) {
|
||||
if ($this->enhanced()) {
|
||||
$config = $this->getconfig();
|
||||
if($config) {
|
||||
if ($config) {
|
||||
return (bool) $config->enabled;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getconfig()
|
||||
{
|
||||
$explode = explode('\\', $this->class);
|
||||
|
||||
// $explode = explode('\\', $this->class);
|
||||
|
||||
if(!isset($this->description) || empty($this->description)) {
|
||||
if (! isset($this->description) || empty($this->description)) {
|
||||
$config = new \stdClass;
|
||||
$config->name = end($explode);
|
||||
// $config->name = end($explode);
|
||||
$config->enabled = false;
|
||||
$config->override_url = null;
|
||||
$config->apikey = null;
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
|
||||
|
||||
$config = json_decode($this->description);
|
||||
|
||||
$config->name = end($explode);
|
||||
// $config->name = end($explode);
|
||||
|
||||
|
||||
$config->url = $this->url;
|
||||
if(isset($config->override_url) && !empty($config->override_url)) {
|
||||
if (isset($config->override_url) && ! empty($config->override_url)) {
|
||||
$config->url = $config->override_url;
|
||||
} else {
|
||||
$config->override_url = null;
|
||||
}
|
||||
|
||||
|
||||
return $config;
|
||||
}
|
||||
|
||||
public static function applicationDetails($class)
|
||||
{
|
||||
if(!empty($class)) {
|
||||
if (! empty($class)) {
|
||||
$name = self::nameFromClass($class);
|
||||
$application = Application::where('name', $name)->first();
|
||||
if($application) return $application;
|
||||
if ($application) {
|
||||
return $application;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
public static function getApplicationDescription($class)
|
||||
{
|
||||
$details = self::applicationDetails($class);
|
||||
if($details !== false) {
|
||||
if ($details !== false) {
|
||||
return $details->description.' - '.$details->license;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -249,8 +252,6 @@ class Item extends Model
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('App\User');
|
||||
}
|
||||
|
||||
|
||||
return $this->belongsTo(\App\User::class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,5 +6,4 @@ use Illuminate\Database\Eloquent\Relations\Pivot;
|
||||
|
||||
class ItemTag extends Pivot
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,15 +2,19 @@
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Application;
|
||||
use App\Item;
|
||||
use App\SupportedApps;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use App\Application;
|
||||
use App\SupportedApps;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class ProcessApps implements ShouldQueue
|
||||
class ProcessApps implements ShouldQueue, ShouldBeUnique
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
@@ -31,36 +35,25 @@ class ProcessApps implements ShouldQueue
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$localapps = Application::all();
|
||||
$list = json_decode(SupportedApps::getList()->getBody());
|
||||
$validapps = [];
|
||||
|
||||
foreach($list->apps as $app) {
|
||||
$validapps[] = $app->appid;
|
||||
$localapp = $localapps->where('appid', $app->appid)->first();
|
||||
Log::debug('Process Apps dispatched');
|
||||
$localapps = Application::whereNull('class')->get();
|
||||
$json = SupportedApps::getList()->getBody();
|
||||
|
||||
$application = ($localapp) ? $localapp : new Application;
|
||||
Storage::disk('local')->put('supportedapps.json', $json);
|
||||
|
||||
if(!file_exists(app_path('SupportedApps/'.className($app->name)))) {
|
||||
SupportedApps::getFiles($app);
|
||||
SupportedApps::saveApp($app, $application);
|
||||
} else {
|
||||
// check if there has been an update for this app
|
||||
$localapp = $localapps->where('appid', $app->appid)->first();
|
||||
if($localapp) {
|
||||
if($localapp->sha !== $app->sha) {
|
||||
SupportedApps::getFiles($app);
|
||||
SupportedApps::saveApp($app, $application);
|
||||
}
|
||||
} else {
|
||||
SupportedApps::getFiles($app);
|
||||
SupportedApps::saveApp($app, $application);
|
||||
|
||||
foreach ($localapps as $app) {
|
||||
$app->class = $app->class();
|
||||
$app->save();
|
||||
}
|
||||
|
||||
$items = Item::whereNotNull('class')->get();
|
||||
foreach ($items as $item) {
|
||||
if (! file_exists(app_path('SupportedApps/'.Item::nameFromClass($item->class)))) {
|
||||
$app = Application::where('class', $item->class)->first();
|
||||
if ($app) {
|
||||
Application::getApp($app->appid);
|
||||
}
|
||||
}
|
||||
}
|
||||
//$delete = Application::whereNotIn('appid', $validapps)->delete(); // delete any apps not in list
|
||||
// removed the delete so local apps can be added
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
58
app/Jobs/UpdateApps.php
Normal file
58
app/Jobs/UpdateApps.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Application;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class UpdateApps implements ShouldQueue, ShouldBeUnique
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
Log::debug('Update of all apps triggered!');
|
||||
$apps = Application::all('appid')->toArray();
|
||||
|
||||
// We onl update the apps that are actually in use by items
|
||||
// 1 sec delay after each update to throttle the requests
|
||||
foreach ($apps as $appKey => $app) {
|
||||
Application::getApp($app['appid']);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
Log::debug('Update of all apps finished!');
|
||||
|
||||
Cache::lock('updateApps')->forceRelease();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function failed($exception)
|
||||
{
|
||||
Cache::lock('updateApps')->forceRelease();
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,15 @@
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Artisan;
|
||||
use Schema;
|
||||
use App\Setting;
|
||||
use App\User;
|
||||
use App\Application;
|
||||
use App\Jobs\ProcessApps;
|
||||
use App\Jobs\UpdateApps;
|
||||
use App\Setting;
|
||||
use App\User;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
@@ -19,71 +21,43 @@ class AppServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
|
||||
if(!is_file(base_path('.env'))) {
|
||||
copy(base_path('.env.example'), base_path('.env'));
|
||||
}
|
||||
$this->genKey();
|
||||
if(!is_file(database_path('app.sqlite'))) {
|
||||
// first time setup
|
||||
touch(database_path('app.sqlite'));
|
||||
Artisan::call('migrate', array('--path' => 'database/migrations', '--force' => true, '--seed' => true));
|
||||
//Cache
|
||||
//Artisan::call('config:cache');
|
||||
//Artisan::call('route:cache');
|
||||
}
|
||||
if(is_file(database_path('app.sqlite'))) {
|
||||
if(Schema::hasTable('settings')) {
|
||||
|
||||
// check version to see if an upgrade is needed
|
||||
$db_version = Setting::_fetch('version');
|
||||
$app_version = config('app.version');
|
||||
if(version_compare($app_version, $db_version) == 1) { // app is higher than db, so need to run migrations etc
|
||||
Artisan::call('migrate', array('--path' => 'database/migrations', '--force' => true, '--seed' => true));
|
||||
}
|
||||
|
||||
} else {
|
||||
Artisan::call('migrate', array('--path' => 'database/migrations', '--force' => true, '--seed' => true));
|
||||
}
|
||||
|
||||
if (! class_exists('ZipArchive')) {
|
||||
die('You are missing php-zip');
|
||||
}
|
||||
|
||||
if(!is_file(public_path('storage/.gitignore'))) {
|
||||
$this->createEnvFile();
|
||||
|
||||
$this->setupDatabase();
|
||||
|
||||
if (! is_file(public_path('storage/.gitignore'))) {
|
||||
Artisan::call('storage:link');
|
||||
\Session::put('current_user', null);
|
||||
}
|
||||
|
||||
|
||||
$applications = Application::all();
|
||||
if($applications->count() <= 0) {
|
||||
if (class_exists('ZipArchive')) {
|
||||
ProcessApps::dispatch();
|
||||
} else {
|
||||
die("You are missing php-zip");
|
||||
}
|
||||
|
||||
|
||||
if ($applications->count() <= 0) {
|
||||
ProcessApps::dispatch();
|
||||
}
|
||||
|
||||
// User specific settings need to go here as session isn't available at this point in the app
|
||||
view()->composer('*', function ($view)
|
||||
{
|
||||
|
||||
if(isset($_SERVER['HTTP_AUTHORIZATION']) && !empty($_SERVER['HTTP_AUTHORIZATION'])) {
|
||||
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) =
|
||||
view()->composer('*', function ($view) {
|
||||
if (isset($_SERVER['HTTP_AUTHORIZATION']) && ! empty($_SERVER['HTTP_AUTHORIZATION'])) {
|
||||
list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) =
|
||||
explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
|
||||
}
|
||||
if(!\Auth::check()) {
|
||||
if(isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])
|
||||
&& !empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_PW'])) {
|
||||
if (! \Auth::check()) {
|
||||
if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])
|
||||
&& ! empty($_SERVER['PHP_AUTH_USER']) && ! empty($_SERVER['PHP_AUTH_PW'])) {
|
||||
$credentials = ['username' => $_SERVER['PHP_AUTH_USER'], 'password' => $_SERVER['PHP_AUTH_PW']];
|
||||
|
||||
|
||||
if (\Auth::attempt($credentials, true)) {
|
||||
// Authentication passed...
|
||||
$user = \Auth::user();
|
||||
//\Session::put('current_user', $user);
|
||||
session(['current_user' => $user]);
|
||||
session(['current_user' => $user]);
|
||||
}
|
||||
}
|
||||
elseif(isset($_SERVER['REMOTE_USER']) && !empty($_SERVER['REMOTE_USER'])) {
|
||||
} elseif (isset($_SERVER['REMOTE_USER']) && ! empty($_SERVER['REMOTE_USER'])) {
|
||||
$user = User::where('username', $_SERVER['REMOTE_USER'])->first();
|
||||
if ($user) {
|
||||
\Auth::login($user, true);
|
||||
@@ -92,54 +66,47 @@ class AppServiceProvider extends ServiceProvider
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$alt_bg = '';
|
||||
if($bg_image = Setting::fetch('background_image')) {
|
||||
if ($bg_image = Setting::fetch('background_image')) {
|
||||
$alt_bg = ' style="background-image: url(storage/'.$bg_image.')"';
|
||||
}
|
||||
$lang = Setting::fetch('language');
|
||||
\App::setLocale($lang);
|
||||
|
||||
$allusers = User::all();
|
||||
$current_user = User::currentUser();
|
||||
|
||||
$view->with('alt_bg', $alt_bg );
|
||||
$view->with('allusers', $allusers );
|
||||
$view->with('current_user', $current_user );
|
||||
$lang = Setting::fetch('language');
|
||||
\App::setLocale($lang);
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
$view->with('alt_bg', $alt_bg);
|
||||
$view->with('allusers', $allusers);
|
||||
$view->with('current_user', $current_user);
|
||||
});
|
||||
|
||||
$this->app['view']->addNamespace('SupportedApps', app_path('SupportedApps'));
|
||||
|
||||
|
||||
if (env('FORCE_HTTPS') === true) {
|
||||
\URL::forceScheme('https');
|
||||
}
|
||||
|
||||
if(env('APP_URL') != 'http://localhost') {
|
||||
if (env('APP_URL') != 'http://localhost') {
|
||||
\URL::forceRootUrl(env('APP_URL'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Generate app key if missing and .env exists
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function genKey()
|
||||
{
|
||||
if(is_file(base_path('.env'))) {
|
||||
if(empty(env('APP_KEY'))) {
|
||||
Artisan::call('key:generate', array('--force' => true, '--no-interaction' => true));
|
||||
if (is_file(base_path('.env'))) {
|
||||
if (empty(env('APP_KEY'))) {
|
||||
Artisan::call('key:generate', ['--force' => true, '--no-interaction' => true]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register any application services.
|
||||
*
|
||||
@@ -151,4 +118,65 @@ class AppServiceProvider extends ServiceProvider
|
||||
return new Setting();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if database needs an update or do first time database setup
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setupDatabase(): void
|
||||
{
|
||||
$db_type = config()->get('database.default');
|
||||
|
||||
if ($db_type == 'sqlite' && ! is_file(database_path('app.sqlite'))) {
|
||||
touch(database_path('app.sqlite'));
|
||||
}
|
||||
|
||||
if ($this->needsDBUpdate()) {
|
||||
Artisan::call('migrate', ['--path' => 'database/migrations', '--force' => true, '--seed' => true]);
|
||||
ProcessApps::dispatchSync();
|
||||
$this->updateApps();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function createEnvFile(): void
|
||||
{
|
||||
if (!is_file(base_path('.env'))) {
|
||||
copy(base_path('.env.example'), base_path('.env'));
|
||||
}
|
||||
|
||||
$this->genKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function needsDBUpdate(): bool
|
||||
{
|
||||
if (!Schema::hasTable('settings')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$db_version = Setting::_fetch('version');
|
||||
$app_version = config('app.version');
|
||||
|
||||
return version_compare($app_version, $db_version) === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
private function updateApps()
|
||||
{
|
||||
// This lock ensures that the job is not invoked multiple times.
|
||||
// In 5 minutes all app updates should be finished.
|
||||
$lock = Cache::lock('updateApps', 5*60);
|
||||
|
||||
if ($lock->get()) {
|
||||
UpdateApps::dispatchAfterResponse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||
|
||||
class AuthServiceProvider extends ServiceProvider
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Facades\Broadcast;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class BroadcastServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||
|
||||
class EventServiceProvider extends ServiceProvider
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
class RouteServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
||||
@@ -1,52 +1,53 @@
|
||||
<?php namespace App;
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
use App\Item;
|
||||
use App\Setting;
|
||||
use Form;
|
||||
use Cache;
|
||||
use Form;
|
||||
use Yaml;
|
||||
|
||||
abstract class Search
|
||||
{
|
||||
|
||||
/**
|
||||
* List of all search providers
|
||||
*
|
||||
* @return Array
|
||||
*
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public static function providers()
|
||||
{
|
||||
$providers = self::standardProviders();
|
||||
$providers = $providers + self::appProviders();
|
||||
|
||||
return collect($providers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets details for a single provider
|
||||
*
|
||||
* @return Object
|
||||
*
|
||||
* @return false|object
|
||||
*/
|
||||
public static function providerDetails($provider)
|
||||
{
|
||||
$providers = self::providers();
|
||||
if(!isset($providers[$provider])) return false;
|
||||
return (object)$providers[$provider] ?? false;
|
||||
if (! isset($providers[$provider])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (object) $providers[$provider] ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Array of the standard providers
|
||||
*
|
||||
* @return Array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function standardProviders()
|
||||
public static function standardProviders(): array
|
||||
{
|
||||
// $providers = json_decode(file_get_contents(storage_path('app/searchproviders.json')));
|
||||
// print_r($providers);
|
||||
$providers = Yaml::parseFile(storage_path('app/searchproviders.yaml'));
|
||||
$all = [];
|
||||
foreach($providers as $key => $provider) {
|
||||
foreach ($providers as $key => $provider) {
|
||||
$all[$key] = $provider;
|
||||
$all[$key]['type'] = 'standard';
|
||||
}
|
||||
@@ -57,16 +58,18 @@ abstract class Search
|
||||
/**
|
||||
* Loops through users apps to see if app is a search provider, might be worth
|
||||
* looking into caching this at some point
|
||||
*
|
||||
* @return Array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function appProviders()
|
||||
{
|
||||
$providers = [];
|
||||
$userapps = Item::all();
|
||||
foreach($userapps as $app) {
|
||||
if(empty($app->class)) continue;
|
||||
if(($provider = Item::isSearchProvider($app->class)) !== false) {
|
||||
foreach ($userapps as $app) {
|
||||
if (empty($app->class)) {
|
||||
continue;
|
||||
}
|
||||
if (($provider = Item::isSearchProvider($app->class)) !== false) {
|
||||
$name = Item::nameFromClass($app->class);
|
||||
$providers[$app->id] = [
|
||||
'id' => $app->id,
|
||||
@@ -76,35 +79,36 @@ abstract class Search
|
||||
'name' => $app->title,
|
||||
'colour' => $app->colour,
|
||||
'icon' => $app->icon,
|
||||
'description' => $app->description
|
||||
'description' => $app->description,
|
||||
];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return $providers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the search form
|
||||
*
|
||||
* @return html
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function form()
|
||||
public static function form(): string
|
||||
{
|
||||
$output = '';
|
||||
$homepage_search = Setting::fetch('homepage_search');
|
||||
$search_provider = Setting::where('key', '=', 'search_provider')->first();
|
||||
$user_search_provider = Setting::fetch('search_provider');
|
||||
//die(print_r($search_provider));
|
||||
|
||||
|
||||
//die(var_dump($user_search_provider));
|
||||
// return early if search isn't applicable
|
||||
if((bool)$homepage_search !== true) return $output;
|
||||
if ((bool) $homepage_search !== true) {
|
||||
return $output;
|
||||
}
|
||||
$user_search_provider = $user_search_provider ?? 'none';
|
||||
|
||||
if((bool)$homepage_search && (bool)$search_provider) {
|
||||
|
||||
if((bool)$user_search_provider) {
|
||||
if ((bool) $search_provider) {
|
||||
if ((bool) $user_search_provider) {
|
||||
$name = 'app.options.'.$user_search_provider;
|
||||
$provider = self::providerDetails($user_search_provider);
|
||||
|
||||
@@ -112,8 +116,8 @@ abstract class Search
|
||||
$output .= '<form action="'.url('search').'"'.getLinkTargetAttribute().' method="get">';
|
||||
$output .= '<div id="search-container" class="input-container">';
|
||||
$output .= '<select name="provider">';
|
||||
foreach(self::providers() as $key => $searchprovider) {
|
||||
$selected = ((string)$key === (string)$user_search_provider) ? ' selected="selected"' : '';
|
||||
foreach (self::providers() as $key => $searchprovider) {
|
||||
$selected = ((string) $key === (string) $user_search_provider) ? ' selected="selected"' : '';
|
||||
$output .= '<option value="'.$key.'"'.$selected.'>'.$searchprovider['name'].'</option>';
|
||||
}
|
||||
$output .= '</select>';
|
||||
@@ -124,8 +128,7 @@ abstract class Search
|
||||
$output .= '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
<?php namespace App;
|
||||
<?php
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
namespace App;
|
||||
|
||||
interface SearchInterface
|
||||
{
|
||||
public function getResults($query, $providerdetails);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
141
app/Setting.php
141
app/Setting.php
@@ -2,13 +2,10 @@
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Form;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\User;
|
||||
use App\Search;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
|
||||
class Setting extends Model
|
||||
{
|
||||
@@ -20,7 +17,7 @@ class Setting extends Model
|
||||
protected $table = 'settings';
|
||||
|
||||
protected $fillable = [
|
||||
'id', 'group_id', 'key', 'type', 'options', 'label', 'value', 'order', 'system'
|
||||
'id', 'group_id', 'key', 'type', 'options', 'label', 'value', 'order', 'system',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -38,9 +35,10 @@ class Setting extends Model
|
||||
protected static $cache = [];
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @param Request $request
|
||||
* @return object
|
||||
*/
|
||||
public static function getInput(Request $request)
|
||||
public static function getInput(Request $request): object
|
||||
{
|
||||
return (object) [
|
||||
'value' => $request->input('value'),
|
||||
@@ -50,37 +48,37 @@ class Setting extends Model
|
||||
|
||||
public function getListValueAttribute()
|
||||
{
|
||||
if((bool)$this->system === true) {
|
||||
if ((bool) $this->system === true) {
|
||||
$value = self::_fetch($this->key);
|
||||
} else {
|
||||
$value = self::fetch($this->key);
|
||||
}
|
||||
$this->value = $value;
|
||||
switch($this->type) {
|
||||
switch ($this->type) {
|
||||
case 'image':
|
||||
if(!empty($this->value)) {
|
||||
if (! empty($this->value)) {
|
||||
$value = '<a href="'.asset('storage/'.$this->value).'" title="'.__('app.settings.view').'" target="_blank">'.__('app.settings.view').'</a>';
|
||||
} else {
|
||||
$value = __('app.options.none');
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'boolean':
|
||||
if((bool)$this->value === true) {
|
||||
if ((bool) $this->value === true) {
|
||||
$value = __('app.options.yes');
|
||||
} else {
|
||||
$value = __('app.options.no');
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'select':
|
||||
if(!empty($this->value) && $this->value !== 'none') {
|
||||
$options = (array)json_decode($this->options);
|
||||
if($this->key === 'search_provider') {
|
||||
if (! empty($this->value) && $this->value !== 'none') {
|
||||
$options = (array) json_decode($this->options);
|
||||
if ($this->key === 'search_provider') {
|
||||
$options = Search::providers()->pluck('name', 'id')->toArray();
|
||||
}
|
||||
$value = __($options[$this->value]);
|
||||
}
|
||||
$value = (array_key_exists($this->value, $options)) ? __($options[$this->value]) : __('app.options.none');
|
||||
} else {
|
||||
$value = __('app.options.none');
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$value = __($this->value);
|
||||
@@ -88,32 +86,33 @@ class Setting extends Model
|
||||
}
|
||||
|
||||
return $value;
|
||||
|
||||
}
|
||||
|
||||
public function getEditValueAttribute()
|
||||
{
|
||||
if((bool)$this->system === true) {
|
||||
if ((bool) $this->system === true) {
|
||||
$value = self::_fetch($this->key);
|
||||
} else {
|
||||
$value = self::fetch($this->key);
|
||||
}
|
||||
$this->value = $value;
|
||||
switch($this->type) {
|
||||
switch ($this->type) {
|
||||
case 'image':
|
||||
$value = '';
|
||||
if(isset($this->value) && !empty($this->value)) {
|
||||
if (isset($this->value) && ! empty($this->value)) {
|
||||
$value .= '<a class="setting-view-image" href="'.asset('storage/'.$this->value).'" title="'.__('app.settings.view').'" target="_blank"><img src="'.asset('storage/'.$this->value).'" /></a>';
|
||||
}
|
||||
$value .= Form::file('value', ['class' => 'form-control']);
|
||||
if(isset($this->value) && !empty($this->value)) {
|
||||
if (isset($this->value) && ! empty($this->value)) {
|
||||
$value .= '<a class="settinglink" href="'.route('settings.clear', $this->id).'" title="'.__('app.settings.remove').'">'.__('app.settings.reset').'</a>';
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
case 'boolean':
|
||||
$checked = false;
|
||||
if(isset($this->value) && (bool)$this->value === true) $checked = true;
|
||||
if (isset($this->value) && (bool) $this->value === true) {
|
||||
$checked = true;
|
||||
}
|
||||
$set_checked = ($checked) ? ' checked="checked"' : '';
|
||||
$value = '
|
||||
<input type="hidden" name="value" value="0" />
|
||||
@@ -125,10 +124,10 @@ class Setting extends Model
|
||||
break;
|
||||
case 'select':
|
||||
$options = json_decode($this->options);
|
||||
if($this->key === 'search_provider') {
|
||||
if ($this->key === 'search_provider') {
|
||||
$options = Search::providers()->pluck('name', 'id');
|
||||
}
|
||||
foreach($options as $key => $opt) {
|
||||
foreach ($options as $key => $opt) {
|
||||
$options->$key = __($opt);
|
||||
}
|
||||
$value = Form::select('value', $options, null, ['class' => 'form-control']);
|
||||
@@ -142,15 +141,13 @@ class Setting extends Model
|
||||
}
|
||||
|
||||
return $value;
|
||||
|
||||
}
|
||||
|
||||
public function group()
|
||||
{
|
||||
return $this->belongsTo('App\SettingGroup', 'group_id');
|
||||
return $this->belongsTo(\App\SettingGroup::class, 'group_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
@@ -159,53 +156,54 @@ class Setting extends Model
|
||||
public static function fetch($key)
|
||||
{
|
||||
$user = self::user();
|
||||
|
||||
return self::_fetch($key, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function _fetch($key, $user=null)
|
||||
public static function _fetch($key, $user = null)
|
||||
{
|
||||
#$cachekey = ($user === null) ? $key : $key.'-'.$user->id;
|
||||
#if (Setting::cached($cachekey)) {
|
||||
# return Setting::$cache[$cachekey];
|
||||
#} else {
|
||||
$find = self::where('key', '=', $key)->first();
|
||||
//$cachekey = ($user === null) ? $key : $key.'-'.$user->id;
|
||||
//if (Setting::cached($cachekey)) {
|
||||
// return Setting::$cache[$cachekey];
|
||||
//} else {
|
||||
$find = self::where('key', '=', $key)->first();
|
||||
|
||||
if (!is_null($find)) {
|
||||
if((bool)$find->system === true) { // if system variable use global value
|
||||
if (! is_null($find)) {
|
||||
if ((bool) $find->system === true) { // if system variable use global value
|
||||
$value = $find->value;
|
||||
} else { // not system variable so use user specific value
|
||||
// check if user specified value has been set
|
||||
//print_r($user);
|
||||
$usersetting = $user->settings()->where('id', $find->id)->first();
|
||||
//print_r($user->settings);
|
||||
//die(var_dump($usersetting));
|
||||
//->pivot->value;
|
||||
//echo "user: ".$user->id." --- ".$usersettings;
|
||||
if (isset($usersetting) && ! empty($usersetting)) {
|
||||
$value = $usersetting->pivot->uservalue;
|
||||
} else { // if not get default from base setting
|
||||
//$user->settings()->save($find, ['value' => $find->value]);
|
||||
//$has_setting = $user->settings()->where('id', $find->id)->exists();
|
||||
//if($has_setting) {
|
||||
// $user->settings()->updateExistingPivot($find->id, ['uservalue' => (string)$find->value]);
|
||||
//} else {
|
||||
// $user->settings()->save($find, ['uservalue' => (string)$find->value]);
|
||||
//}
|
||||
$value = $find->value;
|
||||
} else { // not system variable so use user specific value
|
||||
// check if user specified value has been set
|
||||
//print_r($user);
|
||||
$usersetting = $user->settings()->where('id', $find->id)->first();
|
||||
//print_r($user->settings);
|
||||
//die(var_dump($usersetting));
|
||||
//->pivot->value;
|
||||
//echo "user: ".$user->id." --- ".$usersettings;
|
||||
if(isset($usersetting) && !empty($usersetting)) {
|
||||
$value = $usersetting->pivot->uservalue;
|
||||
} else { // if not get default from base setting
|
||||
//$user->settings()->save($find, ['value' => $find->value]);
|
||||
#$has_setting = $user->settings()->where('id', $find->id)->exists();
|
||||
#if($has_setting) {
|
||||
# $user->settings()->updateExistingPivot($find->id, ['uservalue' => (string)$find->value]);
|
||||
#} else {
|
||||
# $user->settings()->save($find, ['uservalue' => (string)$find->value]);
|
||||
#}
|
||||
$value = $find->value;
|
||||
}
|
||||
|
||||
}
|
||||
#Setting::add($cachekey, $value);
|
||||
|
||||
return $value;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
#}
|
||||
//Setting::add($cachekey, $value);
|
||||
|
||||
return $value;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,7 +212,7 @@ class Setting extends Model
|
||||
*/
|
||||
public static function add($key, $value)
|
||||
{
|
||||
Setting::$cache[$key] = $value;
|
||||
self::$cache[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,22 +222,19 @@ class Setting extends Model
|
||||
*/
|
||||
public static function cached($key)
|
||||
{
|
||||
return array_key_exists($key, Setting::$cache);
|
||||
return array_key_exists($key, self::$cache);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The users that belong to the setting.
|
||||
*/
|
||||
public function users()
|
||||
{
|
||||
return $this->belongsToMany('App\User')->using('App\SettingUser')->withPivot('uservalue');
|
||||
return $this->belongsToMany(\App\User::class)->using(\App\SettingUser::class)->withPivot('uservalue');
|
||||
}
|
||||
|
||||
public static function user()
|
||||
{
|
||||
return User::currentUser();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,6 @@ class SettingGroup extends Model
|
||||
|
||||
public function settings()
|
||||
{
|
||||
return $this->hasMany('App\Setting', 'group_id');
|
||||
return $this->hasMany(\App\Setting::class, 'group_id');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,36 @@
|
||||
<?php namespace App;
|
||||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
abstract class SupportedApps
|
||||
{
|
||||
|
||||
protected $jar = false;
|
||||
|
||||
protected $method = 'GET';
|
||||
|
||||
protected $error;
|
||||
|
||||
public function appTest($url, $attrs = [], $overridevars=false)
|
||||
public function appTest($url, $attrs = [], $overridevars = false)
|
||||
{
|
||||
if(empty($this->config->url)) {
|
||||
return (object)[
|
||||
if (empty($this->config->url)) {
|
||||
return (object) [
|
||||
'code' => 404,
|
||||
'status' => 'No URL has been specified',
|
||||
'response' => 'No URL has been specified',
|
||||
];
|
||||
];
|
||||
}
|
||||
$res = $this->execute($url, $attrs);
|
||||
if($res == null) {
|
||||
return (object)[
|
||||
if ($res == null) {
|
||||
return (object) [
|
||||
'code' => null,
|
||||
'status' => $this->error,
|
||||
'response' => 'Connection failed',
|
||||
];
|
||||
}
|
||||
switch($res->getStatusCode()) {
|
||||
switch ($res->getStatusCode()) {
|
||||
case 200:
|
||||
$status = 'Successfully communicated with the API';
|
||||
break;
|
||||
@@ -42,21 +44,22 @@ abstract class SupportedApps
|
||||
$status = 'Something went wrong... Code: '.$res->getStatusCode();
|
||||
break;
|
||||
}
|
||||
return (object)[
|
||||
|
||||
return (object) [
|
||||
'code' => $res->getStatusCode(),
|
||||
'status' => $status,
|
||||
'response' => $res->getBody(),
|
||||
];
|
||||
}
|
||||
|
||||
public function execute($url, $attrs = [], $overridevars=false, $overridemethod=false)
|
||||
public function execute($url, $attrs = [], $overridevars = false, $overridemethod = false)
|
||||
{
|
||||
$res = null;
|
||||
|
||||
$vars = ($overridevars !== false) ?
|
||||
$overridevars : [
|
||||
'http_errors' => false,
|
||||
'timeout' => 15,
|
||||
'http_errors' => false,
|
||||
'timeout' => 15,
|
||||
'connect_timeout' => 15,
|
||||
];
|
||||
|
||||
@@ -65,35 +68,34 @@ abstract class SupportedApps
|
||||
$method = ($overridemethod !== false) ? $overridemethod : $this->method;
|
||||
|
||||
try {
|
||||
return $client->request($method, $url, $attrs);
|
||||
return $client->request($method, $url, $attrs);
|
||||
} catch (\GuzzleHttp\Exception\ConnectException $e) {
|
||||
Log::error("Connection refused");
|
||||
Log::error('Connection refused');
|
||||
Log::debug($e->getMessage());
|
||||
$this->error = "Connection refused - ".(string) $e->getMessage();
|
||||
$this->error = 'Connection refused - '.(string) $e->getMessage();
|
||||
} catch (\GuzzleHttp\Exception\ServerException $e) {
|
||||
Log::debug($e->getMessage());
|
||||
$this->error = (string) $e->getResponse()->getBody();
|
||||
}
|
||||
$this->error = 'General error connecting with API';
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function login()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function normaliseurl($url, $addslash=true)
|
||||
public function normaliseurl($url, $addslash = true)
|
||||
{
|
||||
|
||||
$url = rtrim($url, '/');
|
||||
if($addslash) $url .= '/';
|
||||
if ($addslash) {
|
||||
$url .= '/';
|
||||
}
|
||||
|
||||
return $url;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function getLiveStats($status, $data)
|
||||
{
|
||||
$className = get_class($this);
|
||||
@@ -101,31 +103,49 @@ abstract class SupportedApps
|
||||
$name = end($explode);
|
||||
|
||||
$html = view('SupportedApps::'.$name.'.livestats', $data)->with('data', $data)->render();
|
||||
|
||||
return json_encode(['status' => $status, 'html' => $html]);
|
||||
//return
|
||||
//return
|
||||
}
|
||||
|
||||
public static function getList()
|
||||
{
|
||||
$list_url = 'https://apps.heimdall.site/list';
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
// $list_url = 'https://apps.heimdall.site/list';
|
||||
$list_url = config('app.appsource').'list.json';
|
||||
$client = new Client(['http_errors' => false, 'verify' => false, 'timeout' => 15, 'connect_timeout' => 15]);
|
||||
|
||||
return $client->request('GET', $list_url);
|
||||
}
|
||||
|
||||
public static function configValue($item=null, $key=null)
|
||||
public static function configValue($item = null, $key = null)
|
||||
{
|
||||
if(isset($item) && !empty($item)) {
|
||||
if (isset($item) && ! empty($item)) {
|
||||
return $item->getconfig()->$key;
|
||||
} else return null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static function getFiles($app)
|
||||
/**
|
||||
* @param $app
|
||||
* @return bool|false
|
||||
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||
*/
|
||||
public static function getFiles($app): bool
|
||||
{
|
||||
$zipurl = $app->files;
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 60, 'connect_timeout' => 15]);
|
||||
Log::debug("Download triggered for ".print_r($app, true));
|
||||
|
||||
$zipurl = config('app.appsource').'files/'.$app->sha.'.zip';
|
||||
|
||||
$client = new Client(['http_errors' => false, 'timeout' => 60, 'connect_timeout' => 15, 'verify' => false]);
|
||||
$res = $client->request('GET', $zipurl);
|
||||
|
||||
if(!file_exists(app_path('SupportedApps'))) {
|
||||
// Something went wrong?
|
||||
if ($res->getStatusCode() !== 200) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! file_exists(app_path('SupportedApps'))) {
|
||||
mkdir(app_path('SupportedApps'), 0777, true);
|
||||
}
|
||||
|
||||
@@ -138,35 +158,30 @@ abstract class SupportedApps
|
||||
$zip->extractTo(app_path('SupportedApps')); // place in the directory with same name
|
||||
$zip->close();
|
||||
unlink($src); //Deleting the Zipped file
|
||||
} else {
|
||||
var_dump($x);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function saveApp($details, $app)
|
||||
{
|
||||
if(!file_exists(storage_path('app/public/icons'))) {
|
||||
mkdir(storage_path('app/public/icons'), 0777, true);
|
||||
}
|
||||
|
||||
$img_src = app_path('SupportedApps/'.className($details->name).'/'.$details->icon);
|
||||
$img_dest = storage_path('app/public/icons/'.$details->icon);
|
||||
//die("i: ".$img_src);
|
||||
@copy($img_src, $img_dest);
|
||||
|
||||
$app->appid = $details->appid;
|
||||
$app->name = $details->name;
|
||||
$app->sha = $details->sha ?? null;
|
||||
$app->icon = 'icons/'.$details->icon;
|
||||
$app->website = $details->website;
|
||||
$app->license = $details->license;
|
||||
$app->description = $details->description;
|
||||
|
||||
$appclass = $app->class();
|
||||
$application = new $appclass;
|
||||
$enhanced = (bool)($application instanceof \App\EnhancedApps);
|
||||
|
||||
$enhanced = (bool) ($application instanceof \App\EnhancedApps);
|
||||
$app->class = $appclass;
|
||||
$app->enhanced = $enhanced;
|
||||
$app->tile_background = $details->tile_background;
|
||||
$app->save();
|
||||
}
|
||||
|
||||
}
|
||||
return $app;
|
||||
}
|
||||
}
|
||||
|
||||
30
app/User.php
30
app/User.php
@@ -2,8 +2,10 @@
|
||||
|
||||
namespace App;
|
||||
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
@@ -27,20 +29,28 @@ class User extends Authenticatable
|
||||
'password', 'remember_token',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the items for the user.
|
||||
*/
|
||||
public function items()
|
||||
public function items(): HasMany
|
||||
{
|
||||
return $this->hasMany('App\Item');
|
||||
return $this->hasMany(Item::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* The settings that belong to the user.
|
||||
*/
|
||||
public function settings()
|
||||
public function settings(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany('App\Setting')->withPivot('uservalue');
|
||||
return $this->belongsToMany(Setting::class)->withPivot('uservalue');
|
||||
}
|
||||
|
||||
public static function currentUser()
|
||||
@@ -49,15 +59,13 @@ class User extends Authenticatable
|
||||
if ($current_user) { // if logged in, set this user
|
||||
return $current_user;
|
||||
} else { // not logged in, get first user
|
||||
$user = User::where('public_front',true)->first();
|
||||
if(!$user) {
|
||||
$user = User::first();
|
||||
$user = self::where('public_front', true)->first();
|
||||
if (! $user) {
|
||||
$user = self::first();
|
||||
}
|
||||
session(['current_user' => $user]);
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*/
|
||||
|
||||
$app = new Illuminate\Foundation\Application(
|
||||
realpath(__DIR__.'/../')
|
||||
$_ENV['APP_BASE_PATH'] ?? dirname(__DIR__)
|
||||
);
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,37 +1,46 @@
|
||||
{
|
||||
"name": "laravel/laravel",
|
||||
"description": "The Laravel Framework.",
|
||||
"keywords": ["framework", "laravel"],
|
||||
"keywords": [
|
||||
"framework",
|
||||
"laravel"
|
||||
],
|
||||
"license": "MIT",
|
||||
"type": "project",
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"php": ">=7.4.32",
|
||||
"facade/ignition": "^2.3.6",
|
||||
"fideloper/proxy": "^4.0",
|
||||
"graham-campbell/github": "^10.5",
|
||||
"guzzlehttp/guzzle": "^7.4",
|
||||
"laravel/framework": "^7.0",
|
||||
"laravel/framework": "^8.0",
|
||||
"laravel/tinker": "^2.0",
|
||||
"laravel/ui": "^2.4",
|
||||
"laravel/ui": "^3.0",
|
||||
"laravelcollective/html": "^6.0",
|
||||
"symfony/yaml": "^5.4"
|
||||
"nunomaduro/collision": "^5.0",
|
||||
"symfony/yaml": "^5.4",
|
||||
"ext-json": "*",
|
||||
"ext-intl": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"filp/whoops": "~2.0",
|
||||
"fzaninotto/faker": "~1.4",
|
||||
"mockery/mockery": "~1.0",
|
||||
"phpunit/phpunit": "~6.0",
|
||||
"phpunit/phpunit": "~9.0",
|
||||
"symfony/thanks": "^1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"database/seeds",
|
||||
"database/seeders",
|
||||
"database/factories"
|
||||
],
|
||||
"files": [
|
||||
"app/Helper.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"App\\": "app/"
|
||||
"App\\": "app/",
|
||||
"Database\\Factories\\": "database/factories/",
|
||||
"Database\\Seeders\\": "database/seeders/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
|
||||
3177
composer.lock
generated
3177
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -13,8 +13,8 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'name' => env('APP_NAME', 'Heimdall'),
|
||||
'version' => '2.3.2',
|
||||
'name' => env('APP_NAME', 'Heimdall'),
|
||||
'version' => '2.5.2',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -40,7 +40,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'debug' => env('APP_DEBUG', false),
|
||||
'debug' => (bool) env('APP_DEBUG', false),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -55,6 +55,9 @@ return [
|
||||
|
||||
'url' => env('APP_URL', 'http://localhost'),
|
||||
|
||||
'asset_url' => env('ASSET_URL', null),
|
||||
'appsource' => env('APP_SOURCE', 'https://appslist.heimdall.site/'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Timezone
|
||||
@@ -94,6 +97,19 @@ return [
|
||||
|
||||
'fallback_locale' => 'en',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Faker Locale
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This locale will be used by the Faker PHP library when generating fake
|
||||
| data for your database seeds. For example, this will be used to get
|
||||
| localized telephone numbers, street address information and more.
|
||||
|
|
||||
*/
|
||||
|
||||
'faker_locale' => 'en_US',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Encryption Key
|
||||
@@ -109,23 +125,6 @@ return [
|
||||
|
||||
'cipher' => 'AES-256-CBC',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Logging Configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the log settings for your application. Out of
|
||||
| the box, Laravel uses the Monolog PHP logging library. This gives
|
||||
| you a variety of powerful log handlers / formatters to utilize.
|
||||
|
|
||||
| Available Settings: "single", "daily", "syslog", "errorlog"
|
||||
|
|
||||
*/
|
||||
|
||||
'log' => env('APP_LOG', 'single'),
|
||||
|
||||
'log_level' => env('APP_LOG_LEVEL', 'debug'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Autoloaded Service Providers
|
||||
@@ -194,6 +193,7 @@ return [
|
||||
'aliases' => [
|
||||
|
||||
'App' => Illuminate\Support\Facades\App::class,
|
||||
'Arr' => Illuminate\Support\Arr::class,
|
||||
'Artisan' => Illuminate\Support\Facades\Artisan::class,
|
||||
'Auth' => Illuminate\Support\Facades\Auth::class,
|
||||
'Blade' => Illuminate\Support\Facades\Blade::class,
|
||||
@@ -211,6 +211,7 @@ return [
|
||||
'Gate' => Illuminate\Support\Facades\Gate::class,
|
||||
'Hash' => Illuminate\Support\Facades\Hash::class,
|
||||
'Html' => Collective\Html\HtmlFacade::class,
|
||||
'Http' => Illuminate\Support\Facades\Http::class,
|
||||
'Lang' => Illuminate\Support\Facades\Lang::class,
|
||||
'Log' => Illuminate\Support\Facades\Log::class,
|
||||
'Mail' => Illuminate\Support\Facades\Mail::class,
|
||||
@@ -225,6 +226,7 @@ return [
|
||||
'Schema' => Illuminate\Support\Facades\Schema::class,
|
||||
'Session' => Illuminate\Support\Facades\Session::class,
|
||||
'Storage' => Illuminate\Support\Facades\Storage::class,
|
||||
'Str' => Illuminate\Support\Str::class,
|
||||
'URL' => Illuminate\Support\Facades\URL::class,
|
||||
'Validator' => Illuminate\Support\Facades\Validator::class,
|
||||
'View' => Illuminate\Support\Facades\View::class,
|
||||
|
||||
@@ -44,6 +44,7 @@ return [
|
||||
'api' => [
|
||||
'driver' => 'token',
|
||||
'provider' => 'users',
|
||||
'hash' => false,
|
||||
],
|
||||
],
|
||||
|
||||
@@ -96,7 +97,21 @@ return [
|
||||
'provider' => 'users',
|
||||
'table' => 'password_resets',
|
||||
'expire' => 60,
|
||||
'throttle' => 60,
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Confirmation Timeout
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define the amount of seconds before a password confirmation
|
||||
| times out and the user is prompted to re-enter their password via the
|
||||
| confirmation screen. By default, the timeout lasts for three hours.
|
||||
|
|
||||
*/
|
||||
|
||||
'password_timeout' => 10800,
|
||||
|
||||
];
|
||||
|
||||
@@ -37,7 +37,7 @@ return [
|
||||
'app_id' => env('PUSHER_APP_ID'),
|
||||
'options' => [
|
||||
'cluster' => env('PUSHER_APP_CLUSTER'),
|
||||
'encrypted' => true,
|
||||
'useTLS' => true,
|
||||
],
|
||||
],
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
@@ -36,6 +38,7 @@ return [
|
||||
|
||||
'array' => [
|
||||
'driver' => 'array',
|
||||
'serialize' => false,
|
||||
],
|
||||
|
||||
'database' => [
|
||||
@@ -73,6 +76,15 @@ return [
|
||||
'connection' => 'default',
|
||||
],
|
||||
|
||||
'dynamodb' => [
|
||||
'driver' => 'dynamodb',
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||
'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
|
||||
'endpoint' => env('DYNAMODB_ENDPOINT'),
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
@@ -86,9 +98,6 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'prefix' => env(
|
||||
'CACHE_PREFIX',
|
||||
str_slug(env('APP_NAME', 'laravel'), '_').'_cache'
|
||||
),
|
||||
'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache'),
|
||||
|
||||
];
|
||||
|
||||
@@ -44,6 +44,7 @@ return [
|
||||
|
||||
'mysql' => [
|
||||
'driver' => 'mysql',
|
||||
'url' => env('DATABASE_URL'),
|
||||
'host' => env('DB_HOST', '127.0.0.1'),
|
||||
'port' => env('DB_PORT', '3306'),
|
||||
'database' => env('DB_DATABASE', 'forge'),
|
||||
@@ -53,12 +54,17 @@ return [
|
||||
'charset' => 'utf8mb4',
|
||||
'collation' => 'utf8mb4_unicode_ci',
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
'strict' => true,
|
||||
'engine' => null,
|
||||
'options' => extension_loaded('pdo_mysql') ? array_filter([
|
||||
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
|
||||
]) : [],
|
||||
],
|
||||
|
||||
'pgsql' => [
|
||||
'driver' => 'pgsql',
|
||||
'url' => env('DATABASE_URL'),
|
||||
'host' => env('DB_HOST', '127.0.0.1'),
|
||||
'port' => env('DB_PORT', '5432'),
|
||||
'database' => env('DB_DATABASE', 'forge'),
|
||||
@@ -66,12 +72,14 @@ return [
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'charset' => 'utf8',
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
'schema' => 'public',
|
||||
'sslmode' => 'prefer',
|
||||
],
|
||||
|
||||
'sqlsrv' => [
|
||||
'driver' => 'sqlsrv',
|
||||
'url' => env('DATABASE_URL'),
|
||||
'host' => env('DB_HOST', 'localhost'),
|
||||
'port' => env('DB_PORT', '1433'),
|
||||
'database' => env('DB_DATABASE', 'forge'),
|
||||
@@ -79,8 +87,9 @@ return [
|
||||
'password' => env('DB_PASSWORD', ''),
|
||||
'charset' => 'utf8',
|
||||
'prefix' => '',
|
||||
'prefix_indexes' => true,
|
||||
],
|
||||
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|
||||
@@ -61,8 +61,10 @@ return [
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'region' => env('AWS_DEFAULT_REGION'),
|
||||
'bucket' => env('AWS_BUCKET'),
|
||||
'url' => env('AWS_URL'),
|
||||
'endpoint' => env('AWS_ENDPOINT'),
|
||||
],
|
||||
|
||||
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
52
config/hashing.php
Normal file
52
config/hashing.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Hash Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default hash driver that will be used to hash
|
||||
| passwords for your application. By default, the bcrypt algorithm is
|
||||
| used; however, you remain free to modify this option if you wish.
|
||||
|
|
||||
| Supported: "bcrypt", "argon", "argon2id"
|
||||
|
|
||||
*/
|
||||
|
||||
'driver' => 'bcrypt',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Bcrypt Options
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the configuration options that should be used when
|
||||
| passwords are hashed using the Bcrypt algorithm. This will allow you
|
||||
| to control the amount of time it takes to hash the given password.
|
||||
|
|
||||
*/
|
||||
|
||||
'bcrypt' => [
|
||||
'rounds' => env('BCRYPT_ROUNDS', 10),
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Argon Options
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the configuration options that should be used when
|
||||
| passwords are hashed using the Argon algorithm. These will allow you
|
||||
| to control the amount of time it takes to hash the given password.
|
||||
|
|
||||
*/
|
||||
|
||||
'argon' => [
|
||||
'memory' => 1024,
|
||||
'threads' => 2,
|
||||
'time' => 2,
|
||||
],
|
||||
|
||||
];
|
||||
@@ -17,7 +17,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('LOG_CHANNEL', 'stack'),
|
||||
'default' => env('LOG_CHANNEL', 'daily'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -101,4 +101,4 @@ return [
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
];
|
||||
|
||||
@@ -4,18 +4,16 @@ return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Queue Driver
|
||||
| Default Queue Connection Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Laravel's queue API supports an assortment of back-ends via a single
|
||||
| API, giving you convenient access to each back-end using the same
|
||||
| syntax for each one. Here you may set the default queue driver.
|
||||
|
|
||||
| Supported: "sync", "database", "beanstalkd", "sqs", "redis", "null"
|
||||
| syntax for every one. Here you may define a default connection.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('QUEUE_DRIVER', 'sync'),
|
||||
'default' => env('QUEUE_CONNECTION', 'sync'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -26,6 +24,8 @@ return [
|
||||
| is used by your application. A default configuration has been added
|
||||
| for each back-end shipped with Laravel. You are free to add more.
|
||||
|
|
||||
| Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"
|
||||
|
|
||||
*/
|
||||
|
||||
'connections' => [
|
||||
@@ -46,22 +46,25 @@ return [
|
||||
'host' => 'localhost',
|
||||
'queue' => 'default',
|
||||
'retry_after' => 90,
|
||||
'block_for' => 0,
|
||||
],
|
||||
|
||||
'sqs' => [
|
||||
'driver' => 'sqs',
|
||||
'key' => env('SQS_KEY', 'your-public-key'),
|
||||
'secret' => env('SQS_SECRET', 'your-secret-key'),
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
|
||||
'queue' => env('SQS_QUEUE', 'your-queue-name'),
|
||||
'region' => env('SQS_REGION', 'us-east-1'),
|
||||
'suffix' => env('SQS_SUFFIX'),
|
||||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||
],
|
||||
|
||||
'redis' => [
|
||||
'driver' => 'redis',
|
||||
'connection' => 'default',
|
||||
'queue' => 'default',
|
||||
'queue' => env('REDIS_QUEUE', 'default'),
|
||||
'retry_after' => 90,
|
||||
'block_for' => null,
|
||||
],
|
||||
|
||||
],
|
||||
@@ -78,6 +81,7 @@ return [
|
||||
*/
|
||||
|
||||
'failed' => [
|
||||
'driver' => env('QUEUE_FAILED_DRIVER', 'database'),
|
||||
'database' => env('DB_CONNECTION', 'mysql'),
|
||||
'table' => 'failed_jobs',
|
||||
],
|
||||
|
||||
@@ -8,31 +8,26 @@ return [
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This file is for storing the credentials for third party services such
|
||||
| as Stripe, Mailgun, SparkPost and others. This file provides a sane
|
||||
| default location for this type of information, allowing packages
|
||||
| to have a conventional place to find your various credentials.
|
||||
| as Mailgun, Postmark, AWS and more. This file provides the de facto
|
||||
| location for this type of information, allowing packages to have
|
||||
| a conventional file to locate the various service credentials.
|
||||
|
|
||||
*/
|
||||
|
||||
'mailgun' => [
|
||||
'domain' => env('MAILGUN_DOMAIN'),
|
||||
'secret' => env('MAILGUN_SECRET'),
|
||||
'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
|
||||
],
|
||||
|
||||
'postmark' => [
|
||||
'token' => env('POSTMARK_TOKEN'),
|
||||
],
|
||||
|
||||
'ses' => [
|
||||
'key' => env('SES_KEY'),
|
||||
'secret' => env('SES_SECRET'),
|
||||
'region' => 'us-east-1',
|
||||
'key' => env('AWS_ACCESS_KEY_ID'),
|
||||
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
||||
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
|
||||
],
|
||||
|
||||
'sparkpost' => [
|
||||
'secret' => env('SPARKPOST_SECRET'),
|
||||
],
|
||||
|
||||
'stripe' => [
|
||||
'model' => App\User::class,
|
||||
'key' => env('STRIPE_KEY'),
|
||||
'secret' => env('STRIPE_SECRET'),
|
||||
],
|
||||
|
||||
|
||||
];
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
@@ -70,7 +72,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'connection' => null,
|
||||
'connection' => env('SESSION_CONNECTION', null),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -96,7 +98,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'store' => null,
|
||||
'store' => env('SESSION_STORE', null),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -124,7 +126,7 @@ return [
|
||||
|
||||
'cookie' => env(
|
||||
'SESSION_COOKIE',
|
||||
str_slug(env('APP_NAME', 'laravel'), '_').'_session'
|
||||
Str::slug(env('APP_NAME', 'laravel'), '_').'_session'
|
||||
),
|
||||
|
||||
/*
|
||||
@@ -164,7 +166,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'secure' => env('SESSION_SECURE_COOKIE', null),
|
||||
'secure' => env('SESSION_SECURE_COOKIE'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
@@ -28,6 +28,9 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'compiled' => realpath(storage_path('framework/views')),
|
||||
'compiled' => env(
|
||||
'VIEW_COMPILED_PATH',
|
||||
realpath(storage_path('framework/views'))
|
||||
),
|
||||
|
||||
];
|
||||
];
|
||||
@@ -1,23 +1,39 @@
|
||||
<?php
|
||||
|
||||
use Faker\Generator as Faker;
|
||||
namespace Database\Factories;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Model Factories
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This directory should contain each of the model factory definitions for
|
||||
| your application. Factories provide a convenient way to generate new
|
||||
| model instances for testing / seeding your application's database.
|
||||
|
|
||||
*/
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
$factory->define(App\User::class, function (Faker $faker) {
|
||||
return [
|
||||
'name' => $faker->name,
|
||||
'email' => $faker->unique()->safeEmail,
|
||||
'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secret
|
||||
'remember_token' => str_random(10),
|
||||
];
|
||||
});
|
||||
class UserFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
return [
|
||||
'name' => $this->faker->name(),
|
||||
'email' => $this->faker->unique()->safeEmail(),
|
||||
'email_verified_at' => now(),
|
||||
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
|
||||
'remember_token' => Str::random(10),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate that the model's email address should be unverified.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Factories\Factory
|
||||
*/
|
||||
public function unverified()
|
||||
{
|
||||
return $this->state(function (array $attributes) {
|
||||
return [
|
||||
'email_verified_at' => null,
|
||||
];
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateItemsTable extends Migration
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateSettingsTable extends Migration
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateSettingGroupsTable extends Migration
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddColumnsToItemsForGroups extends Migration
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class ItemTag extends Migration
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateUsersTable extends Migration
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreatePasswordResetsTable extends Migration
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddUserIdToItemsTable extends Migration
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateSettingUserPivotTable extends Migration
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateApplicationsTable extends Migration
|
||||
{
|
||||
@@ -14,7 +14,6 @@ class CreateApplicationsTable extends Migration
|
||||
public function up()
|
||||
{
|
||||
Schema::create('applications', function (Blueprint $table) {
|
||||
|
||||
$table->string('appid')->unique();
|
||||
$table->string('name')->unique();
|
||||
$table->string('sha')->unique()->nullable();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddClassToItemsTable extends Migration
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateJobsTable extends Migration
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateFailedJobsTable extends Migration
|
||||
{
|
||||
|
||||
32
database/migrations/2022_03_15_140911_add_appid_to_items.php
Normal file
32
database/migrations/2022_03_15_140911_add_appid_to_items.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddAppidToItems extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('items', function (Blueprint $table) {
|
||||
$table->string('appid')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('items', function (Blueprint $table) {
|
||||
$table->dropColumn(['appid']);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddClassToApplication extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('applications', function (Blueprint $table) {
|
||||
$table->string('class')->nullable()->index();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('applications', function (Blueprint $table) {
|
||||
$table->dropColumn(['class']);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddAppDescriptionToItems extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('items', function (Blueprint $table) {
|
||||
$table->text('appdescription')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('items', function (Blueprint $table) {
|
||||
//
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class DatabaseSeeder extends Seeder
|
||||
@@ -1,11 +1,51 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Setting;
|
||||
use App\SettingGroup;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Locale;
|
||||
|
||||
class SettingsSeeder extends Seeder
|
||||
{
|
||||
|
||||
/**
|
||||
* @return false|string
|
||||
*/
|
||||
public static function getSupportedLanguageMap()
|
||||
{
|
||||
if (! class_exists('Locale')) {
|
||||
Log::info('PHP Extension Intl not found. Falling back to English language support only.');
|
||||
return json_encode(['en' => 'English']);
|
||||
}
|
||||
|
||||
$languageDirectories = array_filter(glob(resource_path().'/lang/*'), 'is_dir');
|
||||
$result = [];
|
||||
|
||||
foreach ($languageDirectories as $languageDirectory) {
|
||||
$language = self::getLanguageFromDirectory($languageDirectory);
|
||||
$resultNative = mb_convert_case(Locale::getDisplayLanguage($language.'-', $language), MB_CASE_TITLE, 'UTF-8');
|
||||
$resultEn = ucfirst(Locale::getDisplayLanguage($language, 'en'));
|
||||
$result[$language] = "$resultNative ($resultEn)";
|
||||
}
|
||||
|
||||
return json_encode($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $languageDirectory
|
||||
* @return false|string[]
|
||||
*/
|
||||
public static function getLanguageFromDirectory($languageDirectory)
|
||||
{
|
||||
$directories = explode('/', $languageDirectory);
|
||||
|
||||
return $directories[array_key_last($directories)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
@@ -14,7 +54,7 @@ class SettingsSeeder extends Seeder
|
||||
public function run()
|
||||
{
|
||||
// Groups
|
||||
if(!$setting_group = SettingGroup::find(1)) {
|
||||
if (! $setting_group = SettingGroup::find(1)) {
|
||||
$setting_group = new SettingGroup;
|
||||
$setting_group->id = 1;
|
||||
$setting_group->title = 'app.settings.system';
|
||||
@@ -24,7 +64,7 @@ class SettingsSeeder extends Seeder
|
||||
$setting_group->title = 'app.settings.system';
|
||||
$setting_group->save();
|
||||
}
|
||||
if(!$setting_group = SettingGroup::find(2)) {
|
||||
if (! $setting_group = SettingGroup::find(2)) {
|
||||
$setting_group = new SettingGroup;
|
||||
$setting_group->id = 2;
|
||||
$setting_group->title = 'app.settings.appearance';
|
||||
@@ -34,7 +74,7 @@ class SettingsSeeder extends Seeder
|
||||
$setting_group->title = 'app.settings.appearance';
|
||||
$setting_group->save();
|
||||
}
|
||||
if(!$setting_group = SettingGroup::find(3)) {
|
||||
if (! $setting_group = SettingGroup::find(3)) {
|
||||
$setting_group = new SettingGroup;
|
||||
$setting_group->id = 3;
|
||||
$setting_group->title = 'app.settings.miscellaneous';
|
||||
@@ -44,7 +84,7 @@ class SettingsSeeder extends Seeder
|
||||
$setting_group->title = 'app.settings.miscellaneous';
|
||||
$setting_group->save();
|
||||
}
|
||||
if(!$setting_group = SettingGroup::find(4)) {
|
||||
if (! $setting_group = SettingGroup::find(4)) {
|
||||
$setting_group = new SettingGroup;
|
||||
$setting_group->id = 4;
|
||||
$setting_group->title = 'app.settings.advanced';
|
||||
@@ -55,7 +95,7 @@ class SettingsSeeder extends Seeder
|
||||
$setting_group->save();
|
||||
}
|
||||
|
||||
if($version = Setting::find(1)) {
|
||||
if ($version = Setting::find(1)) {
|
||||
$version->label = 'app.settings.version';
|
||||
$version->value = config('app.version');
|
||||
$version->save();
|
||||
@@ -71,7 +111,7 @@ class SettingsSeeder extends Seeder
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
if(!$setting = Setting::find(2)) {
|
||||
if (! $setting = Setting::find(2)) {
|
||||
$setting = new Setting;
|
||||
$setting->id = 2;
|
||||
$setting->group_id = 2;
|
||||
@@ -83,7 +123,7 @@ class SettingsSeeder extends Seeder
|
||||
$setting->label = 'app.settings.background_image';
|
||||
$setting->save();
|
||||
}
|
||||
if(!$setting = Setting::find(3)) {
|
||||
if (! $setting = Setting::find(3)) {
|
||||
$setting = new Setting;
|
||||
$setting->id = 3;
|
||||
$setting->group_id = 3;
|
||||
@@ -105,8 +145,7 @@ class SettingsSeeder extends Seeder
|
||||
'startpage' => 'app.options.startpage',
|
||||
]);
|
||||
|
||||
if(!$setting = Setting::find(4)) {
|
||||
|
||||
if (! $setting = Setting::find(4)) {
|
||||
$setting = new Setting;
|
||||
$setting->id = 4;
|
||||
$setting->group_id = 3;
|
||||
@@ -121,21 +160,9 @@ class SettingsSeeder extends Seeder
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
$language_options = SettingsSeeder::getSupportedLanguageMap();
|
||||
|
||||
$language_options = json_encode([
|
||||
'de' => 'Deutsch (German)',
|
||||
'en' => 'English',
|
||||
'fi' => 'Suomi (Finnish)',
|
||||
'fr' => 'Français (French)',
|
||||
'el' => 'Ελληνικά (Greek)',
|
||||
'it' => 'Italiano (Italian)',
|
||||
'no' => 'Norsk (Norwegian)',
|
||||
'pl' => 'Polski (Polish)',
|
||||
'sv' => 'Svenska (Swedish)',
|
||||
'es' => 'Español (Spanish)',
|
||||
'tr' => 'Türkçe (Turkish)',
|
||||
]);
|
||||
if($languages = Setting::find(5)) {
|
||||
if ($languages = Setting::find(5)) {
|
||||
$languages->options = $language_options;
|
||||
$languages->save();
|
||||
} else {
|
||||
@@ -156,8 +183,7 @@ class SettingsSeeder extends Seeder
|
||||
'_blank' => 'app.settings.window_target.new',
|
||||
]);
|
||||
|
||||
if(!$setting = Setting::find(7)) {
|
||||
|
||||
if (! $setting = Setting::find(7)) {
|
||||
$setting = new Setting;
|
||||
$setting->id = 7;
|
||||
$setting->group_id = 3;
|
||||
@@ -173,7 +199,7 @@ class SettingsSeeder extends Seeder
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
if($support = Setting::find(8)) {
|
||||
if ($support = Setting::find(8)) {
|
||||
$support->label = 'app.settings.support';
|
||||
$support->value = '<a rel="noopener" target="_blank" href="https://discord.gg/CCjHKn4">Discord</a> | <a rel="noopener" target="_blank" href="https://github.com/linuxserver/Heimdall">Github</a> | <a rel="noopener" target="_blank" href="https://blog.heimdall.site/">Blog</a>';
|
||||
$support->save();
|
||||
@@ -189,7 +215,7 @@ class SettingsSeeder extends Seeder
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
if($donate = Setting::find(9)) {
|
||||
if ($donate = Setting::find(9)) {
|
||||
$donate->label = 'app.settings.donate';
|
||||
$donate->value = '<a rel="noopener" target="_blank" href="https://www.paypal.me/heimdall">Paypal</a>';
|
||||
$donate->save();
|
||||
@@ -204,8 +230,8 @@ class SettingsSeeder extends Seeder
|
||||
$setting->system = true;
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
if(!$setting = Setting::find(10)) {
|
||||
|
||||
if (! $setting = Setting::find(10)) {
|
||||
$setting = new Setting;
|
||||
$setting->id = 10;
|
||||
$setting->group_id = 4;
|
||||
@@ -221,7 +247,7 @@ class SettingsSeeder extends Seeder
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
if(!$setting = Setting::find(11)) {
|
||||
if (! $setting = Setting::find(11)) {
|
||||
$setting = new Setting;
|
||||
$setting->id = 11;
|
||||
$setting->group_id = 4;
|
||||
@@ -237,7 +263,7 @@ class SettingsSeeder extends Seeder
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
if(!$home_tag = \App\Item::find(0)) {
|
||||
if (! $home_tag = \App\Item::find(0)) {
|
||||
$home_tag = new \App\Item;
|
||||
$home_tag->id = 0;
|
||||
$home_tag->title = 'app.dashboard';
|
||||
@@ -245,14 +271,23 @@ class SettingsSeeder extends Seeder
|
||||
$home_tag->url = '';
|
||||
$home_tag->type = 1;
|
||||
$home_tag->user_id = 0;
|
||||
|
||||
$home_tag->save();
|
||||
$home_tag_id = $home_tag->id;
|
||||
|
||||
if($home_tag_id != 0) {
|
||||
Log::info("Home Tag returned with id $home_tag_id from db! Changing to 0.");
|
||||
|
||||
DB::update('update items set id = 0 where id = ?', [$home_tag_id]);
|
||||
}
|
||||
|
||||
$homeapps = \App\Item::withoutGlobalScope('user_id')->doesntHave('parents')->get();
|
||||
foreach($homeapps as $app) {
|
||||
if($app->id === 0) continue;
|
||||
foreach ($homeapps as $app) {
|
||||
if ($app->id === 0) {
|
||||
continue;
|
||||
}
|
||||
$app->parents()->attach(0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
36
database/seeders/UsersSeeder.php
Normal file
36
database/seeders/UsersSeeder.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\User;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class UsersSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
// Groups
|
||||
if (! $user = User::find(1)) {
|
||||
$user = new User;
|
||||
$user->username = 'admin';
|
||||
$user->email = 'admin@test.com';
|
||||
$user->password = null;
|
||||
$user->save();
|
||||
|
||||
$user_id = $user->id;
|
||||
|
||||
if($user_id != 1) {
|
||||
Log::info("First User returned with id $user_id from db! Changing to 1.");
|
||||
|
||||
DB::update('update users set id = 1 where id = ?', [$user_id]);
|
||||
}
|
||||
} else {
|
||||
//$user->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use App\User;
|
||||
|
||||
class UsersSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
// Groups
|
||||
if(!$user = User::find(1)) {
|
||||
$user = new User;
|
||||
$user->id = 1;
|
||||
$user->username = 'admin';
|
||||
$user->email = 'admin@test.com';
|
||||
$user->password = null;
|
||||
$user->save();
|
||||
} else {
|
||||
//$user->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
14924
package-lock.json
generated
14924
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
23
package.json
23
package.json
@@ -2,22 +2,21 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "npm run development",
|
||||
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||
"watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||
"watch-poll": "npm run watch -- --watch-poll",
|
||||
"hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||
"development": "mix",
|
||||
"watch": "mix watch",
|
||||
"watch-poll": "mix watch -- --watch-options-poll=1000",
|
||||
"hot": "mix watch --hot",
|
||||
"prod": "npm run production",
|
||||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
|
||||
"production": "mix --production"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bootstrap-sass": "^3.4.1",
|
||||
"cross-env": "^5.2.0",
|
||||
"jquery": "^3.4.1",
|
||||
"laravel-mix": "^4.0.16",
|
||||
"sass": "^1.21.0",
|
||||
"sass-loader": "7.*"
|
||||
"bootstrap-sass": "^3.4.3",
|
||||
"jquery": "^3.6.1",
|
||||
"laravel-mix": "^6.0.49",
|
||||
"sass": "^1.56.1",
|
||||
"sass-loader": "13.*"
|
||||
},
|
||||
"dependencies": {
|
||||
"select2": "^4.0.7"
|
||||
"select2": "^4.0.13"
|
||||
}
|
||||
}
|
||||
|
||||
54
phpunit.xml
54
phpunit.xml
@@ -1,31 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
bootstrap="vendor/autoload.php"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false">
|
||||
<testsuites>
|
||||
<testsuite name="Feature">
|
||||
<directory suffix="Test.php">./tests/Feature</directory>
|
||||
</testsuite>
|
||||
|
||||
<testsuite name="Unit">
|
||||
<directory suffix="Test.php">./tests/Unit</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist processUncoveredFilesFromWhitelist="true">
|
||||
<directory suffix=".php">./app</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
<php>
|
||||
<env name="APP_ENV" value="testing"/>
|
||||
<env name="CACHE_DRIVER" value="array"/>
|
||||
<env name="SESSION_DRIVER" value="array"/>
|
||||
<env name="QUEUE_DRIVER" value="sync"/>
|
||||
</php>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true">
|
||||
<coverage processUncoveredFiles="true">
|
||||
<include>
|
||||
<directory suffix=".php">./app</directory>
|
||||
</include>
|
||||
</coverage>
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<directory suffix="Test.php">./tests/Unit</directory>
|
||||
</testsuite>
|
||||
<testsuite name="Feature">
|
||||
<directory suffix="Test.php">./tests/Feature</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<php>
|
||||
<server name="APP_ENV" value="testing"/>
|
||||
<server name="BCRYPT_ROUNDS" value="4"/>
|
||||
<server name="CACHE_DRIVER" value="array"/>
|
||||
<!-- <server name="DB_CONNECTION" value="sqlite"/> -->
|
||||
<!-- <server name="DB_DATABASE" value=":memory:"/> -->
|
||||
<server name="MAIL_MAILER" value="array"/>
|
||||
<server name="QUEUE_CONNECTION" value="sync"/>
|
||||
<server name="SESSION_DRIVER" value="array"/>
|
||||
<server name="TELESCOPE_ENABLED" value="false"/>
|
||||
</php>
|
||||
</phpunit>
|
||||
|
||||
1891
public/css/app.css
vendored
1891
public/css/app.css
vendored
File diff suppressed because one or more lines are too long
742
public/js/app.js
vendored
742
public/js/app.js
vendored
File diff suppressed because one or more lines are too long
1
public/js/fontawesome.js
vendored
1
public/js/fontawesome.js
vendored
@@ -480,6 +480,7 @@ function define(prefix, icons) {
|
||||
/* fas icons */
|
||||
var icons = {
|
||||
"arrow-alt-to-right": [448, 512, [], "f34c", "M448 88v336c0 13.3-10.7 24-24 24h-24c-13.3 0-24-10.7-24-24V88c0-13.3 10.7-24 24-24h24c13.3 0 24 10.7 24 24zM24 320h136v87.7c0 17.8 21.5 26.7 34.1 14.1l152.2-152.2c7.5-7.5 7.5-19.8 0-27.3L194.1 90.1c-12.6-12.6-34.1-3.7-34.1 14.1V192H24c-13.3 0-24 10.7-24 24v80c0 13.3 10.7 24 24 24z"],
|
||||
"arrow-rotate-right": [512, 512, [8635, "arrow-right-rotate", "arrow-rotate-forward", "redo"], "f01e", "M496 48V192c0 17.69-14.31 32-32 32H320c-17.69 0-32-14.31-32-32s14.31-32 32-32h63.39c-29.97-39.7-77.25-63.78-127.6-63.78C167.7 96.22 96 167.9 96 256s71.69 159.8 159.8 159.8c34.88 0 68.03-11.03 95.88-31.94c14.22-10.53 34.22-7.75 44.81 6.375c10.59 14.16 7.75 34.22-6.375 44.81c-39.03 29.28-85.36 44.86-134.2 44.86C132.5 479.9 32 379.4 32 256s100.5-223.9 223.9-223.9c69.15 0 134 32.47 176.1 86.12V48c0-17.69 14.31-32 32-32S496 30.31 496 48z"],
|
||||
"ban": [512, 512, [], "f05e", "M256 8C119.034 8 8 119.033 8 256s111.034 248 248 248 248-111.034 248-248S392.967 8 256 8zm130.108 117.892c65.448 65.448 70 165.481 20.677 235.637L150.47 105.216c70.204-49.356 170.226-44.735 235.638 20.676zM125.892 386.108c-65.448-65.448-70-165.481-20.677-235.637L361.53 406.784c-70.203 49.356-170.226 44.736-235.638-20.676z"],
|
||||
"check": [512, 512, [], "f00c", "M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"],
|
||||
"cloud-download": [640, 512, [], "f0ed", "M537.6 226.6c4.1-10.7 6.4-22.4 6.4-34.6 0-53-43-96-96-96-19.7 0-38.1 6-53.3 16.2C367 64.2 315.3 32 256 32c-88.4 0-160 71.6-160 160 0 2.7.1 5.4.2 8.1C40.2 219.8 0 273.2 0 336c0 79.5 64.5 144 144 144h368c70.7 0 128-57.3 128-128 0-61.9-44-113.6-102.4-125.4zm-139.9 93L305 412.3c-9.4 9.4-24.6 9.4-33.9 0l-92.7-92.7c-9.4-9.4-9.4-24.6 0-33.9l10.8-10.8c9.6-9.6 25.2-9.3 34.5.5l32.4 34.5V184c0-13.3 10.7-24 24-24h16c13.3 0 24 10.7 24 24v125.9l32.4-34.5c9.3-9.9 24.9-10.1 34.5-.5l10.8 10.8c9.2 9.3 9.2 24.5-.1 33.9z"],
|
||||
|
||||
4
public/mix-manifest.json
generated
4
public/mix-manifest.json
generated
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"/css/app.css": "/css/app.css?id=bafda2139c75830558d2",
|
||||
"/js/app.js": "/js/app.js?id=0ff185efa8c02e94999e"
|
||||
"/css/app.css": "/css/app.css?id=9a25947db63214edd4e6f459200dfa62",
|
||||
"/js/app.js": "/js/app.js?id=6d4db31cf508e4b9c767ec2710c256ff"
|
||||
}
|
||||
|
||||
38
readme.md
38
readme.md
@@ -34,7 +34,7 @@ Supported applications are recognized by the title of the application as entered
|
||||
[](https://apps.heimdall.site/applications/foundation)
|
||||
|
||||
## Installing
|
||||
Apart from the Laravel dependencies, namely PHP >= 7.2.5, BCMath PHP Extension, Ctype PHP Extension, Fileinfo PHP extension, JSON PHP Extension, Mbstring PHP Extension, OpenSSL PHP Extension, PDO PHP Extension, Tokenizer PHP Extension, XML PHP Extension, the only other thing Heimdall needs is sqlite support and zip support (php-zip).
|
||||
Apart from the Laravel 8 dependencies, namely PHP >= 7.4.32, BCMath PHP Extension, INTL PHP Extension, Ctype PHP Extension, Fileinfo PHP extension, JSON PHP Extension, Mbstring PHP Extension, OpenSSL PHP Extension, PDO PHP Extension, Tokenizer PHP Extension, XML PHP Extension, the only other thing Heimdall needs is sqlite support and zip support (php-zip).
|
||||
|
||||
If you find you can't change the background make sure `php_fileinfo` is enabled in your php.ini. I believe it should be by default, but one user came across the issue on a windows system.
|
||||
|
||||
@@ -55,6 +55,15 @@ There is also a multi-arch Docker which supports x86-64, armhf and arm64, instru
|
||||
## Updating
|
||||
To update your instance, simply clone this repository or download the zip/tar file with the new version and copy it over the old installation.
|
||||
|
||||
## Search Providers
|
||||
v2.3.0 added the ability for users to customise the search options.
|
||||
|
||||
Options are stored in `/storage/app/searchproviders.yaml` (`/config/www/searchproviders.yaml` on docker installs), feel free to rearrange the options, add new ones, delete ones you don't use, etc.
|
||||
|
||||
Consider contributing to https://github.com/linuxserver/Heimdall/discussions/categories/search-providers to help others add new ones.
|
||||
|
||||
The item at the top of the list `Tiles` allows you to search for apps on your dashboard by name, helpful when you have lots of icons.
|
||||
|
||||
## New background image not being set
|
||||
If you are using the docker image or a default php install you may find images over 2MB wont get set as the background image, you just need to change the `upload_max_filesize` in the php.ini.
|
||||
|
||||
@@ -75,13 +84,26 @@ When you are finished, create a pull request.
|
||||
Currently added languages are
|
||||
|
||||
- English
|
||||
- Breton
|
||||
- Danish
|
||||
- German
|
||||
- Greek
|
||||
- Spanish
|
||||
- Finnish
|
||||
- French
|
||||
- Swedish
|
||||
- Spanish
|
||||
- Turkish
|
||||
- Hungarian
|
||||
- Italian
|
||||
- Korean
|
||||
- Lombard
|
||||
- Dutch
|
||||
- Norwegian
|
||||
- Polish
|
||||
- Portuguese
|
||||
- Russian
|
||||
- Slovenian
|
||||
- Swedish
|
||||
- Turkish
|
||||
- Chinese
|
||||
|
||||
## Web Server Configuration
|
||||
|
||||
@@ -160,6 +182,14 @@ openssl.cafile = /config/heimdall.pem
|
||||
|
||||
Restart the container and the enhanced apps should now be able to access your local HTTP websites. This configuration will survive updating or recreating the Heimdall container.
|
||||
|
||||
## Running offline
|
||||
The apps list is hosted on github, you have a couple of options if you want to run without a connection to the outside world:
|
||||
1) Clone the repository and host it yourself, look at the .github actions file to see how to generate the apps list.
|
||||
2) Download the apps list and store it as a json accessible to heimdall named `list.json`
|
||||
|
||||
With both options all you need to do is add the following to your `.env`
|
||||
`APP_SOURCE=http://localhost/` Where `http://localhost/` is the path to the apps list without the name of the file, so if your file is stored at `https://heimdall.local/list.json` you would put `APP_SOURCE=https://heimdall.local/`
|
||||
|
||||
## Support
|
||||
https://discord.gg/CCjHKn4 or through GitHub issues
|
||||
|
||||
|
||||
@@ -2,6 +2,18 @@ $.when( $.ready ).then(function() {
|
||||
|
||||
var base = (document.querySelector('base') || {}).href;
|
||||
|
||||
var itemID = $('form[data-item-id]').data('item-id');
|
||||
var fakePassword = '*****';
|
||||
|
||||
// If in edit mode and password field is present, fill it with stars
|
||||
if (itemID) {
|
||||
var passwordField = $('input[name="config[password]"]').first();
|
||||
|
||||
if (passwordField.length > 0) {
|
||||
passwordField.attr('value', fakePassword);
|
||||
}
|
||||
}
|
||||
|
||||
if($('.message-container').length) {
|
||||
setTimeout(
|
||||
function()
|
||||
@@ -69,8 +81,13 @@ $.when( $.ready ).then(function() {
|
||||
if(timer < max_timer) timer += 2000;
|
||||
}
|
||||
},
|
||||
complete: function() {
|
||||
// Schedule the next request when the current one's complete
|
||||
complete: function(jqXHR) {
|
||||
if (jqXHR.status > 299) {
|
||||
// Stop polling when we get errors
|
||||
return;
|
||||
}
|
||||
|
||||
// Schedule the next request when the current one's complete
|
||||
livestatsRefreshTimeouts[index] = window.setTimeout(worker, timer);
|
||||
}
|
||||
});
|
||||
@@ -128,6 +145,25 @@ $.when( $.ready ).then(function() {
|
||||
});
|
||||
$('#sortable').sortable('disable');
|
||||
|
||||
$('#main').on('mouseenter', '#sortable.ui-sortable-disabled .item', function () {
|
||||
$(this).siblings('.tooltip').addClass('active')
|
||||
$('.refresh', this).addClass('active')
|
||||
}).on('mouseleave', '.item', function () {
|
||||
$(this).siblings('.tooltip').removeClass('active')
|
||||
$('.refresh', this).removeClass('active')
|
||||
})
|
||||
$('#config-buttons').on('mouseenter', 'a', function () {
|
||||
$('.tooltip', this).addClass('active');
|
||||
}).on('mouseleave', 'a', function () {
|
||||
$('.tooltip', this).removeClass('active');
|
||||
})
|
||||
|
||||
$('.searchform > form').on('submit', function (event) {
|
||||
if ($('#search-container select[name=provider]').val() === 'tiles') {
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
$('#search-container').on('input', 'input[name=q]', function () {
|
||||
const search = this.value
|
||||
const items = $('#sortable').children('.item-container')
|
||||
@@ -173,8 +209,10 @@ $.when( $.ready ).then(function() {
|
||||
$('.add-item').hide();
|
||||
$('.item-edit').hide();
|
||||
$('#app').removeClass('sidebar');
|
||||
$('#sortable .tooltip').css('display', '')
|
||||
$('#sortable').sortable('disable');
|
||||
} else {
|
||||
$('#sortable .tooltip').css('display', 'none')
|
||||
$('#sortable').sortable('enable');
|
||||
setTimeout(function() {
|
||||
$('.add-item').fadeIn();
|
||||
@@ -197,7 +235,7 @@ $.when( $.ready ).then(function() {
|
||||
e.preventDefault();
|
||||
var apiurl = $('#create input[name=url]').val();
|
||||
|
||||
var override_url = $('#create input[name="config[override_url]"]').val();
|
||||
var override_url = $('#sapconfig input[name="config[override_url]"]').val();
|
||||
if(override_url.length && override_url != '') {
|
||||
apiurl = override_url;
|
||||
}
|
||||
@@ -209,6 +247,12 @@ $.when( $.ready ).then(function() {
|
||||
data[config] = $(this).val();
|
||||
});
|
||||
|
||||
data['id'] = $('form[data-item-id]').data('item-id');
|
||||
|
||||
if (data.password && data.password === fakePassword) {
|
||||
data.password = '';
|
||||
}
|
||||
|
||||
$.post(base+'test_config', { data: data }, function(data) {
|
||||
alert(data);
|
||||
});
|
||||
@@ -225,5 +269,13 @@ $.when( $.ready ).then(function() {
|
||||
current.toggleClass('active');
|
||||
});
|
||||
});
|
||||
$('#itemform').on('submit', function(e) {
|
||||
var passwordField = $('input[name="config[password]"]').first();
|
||||
if (passwordField.length > 0) {
|
||||
if (passwordField.attr('value') === fakePassword) {
|
||||
passwordField.attr('value', '');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
35
resources/assets/js/keyBindings.js
vendored
Normal file
35
resources/assets/js/keyBindings.js
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
const focusSearch = event => {
|
||||
const searchInput = document.querySelector('input[name="q"]');
|
||||
if (searchInput) {
|
||||
event.preventDefault();
|
||||
searchInput.focus();
|
||||
}
|
||||
};
|
||||
|
||||
const openFirstNonHiddenItem = event => {
|
||||
if (event.target !== document.querySelector('input[name="q"]')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const item = document.querySelector('#sortable section.item-container:not([style="display: none;"]) a');
|
||||
|
||||
if ('href' in item) {
|
||||
event.preventDefault();
|
||||
window.open(item.href);
|
||||
}
|
||||
};
|
||||
|
||||
const KEY_BINDINGS = {
|
||||
'/': focusSearch,
|
||||
'Enter': openFirstNonHiddenItem
|
||||
};
|
||||
|
||||
document.addEventListener('keydown', function (event) {
|
||||
try {
|
||||
if (event.key in KEY_BINDINGS) {
|
||||
KEY_BINDINGS[event.key](event);
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
});
|
||||
@@ -47,6 +47,66 @@ body {
|
||||
}
|
||||
}
|
||||
}
|
||||
#tile-preview {
|
||||
align-items: center;
|
||||
}
|
||||
.create {
|
||||
.textarea {
|
||||
width: 100%;
|
||||
margin: 0px 20px;
|
||||
textarea{
|
||||
width: 100%;
|
||||
border: 1px solid #dedfe2;
|
||||
padding: 15px;
|
||||
border-radius: 6px;
|
||||
height: 100px;
|
||||
font-size: 14px;
|
||||
}
|
||||
label:not(.switch) {
|
||||
width: 100%;
|
||||
font-size: 13px;
|
||||
color: lighten($app-text, 40%);
|
||||
margin-bottom: 15px;
|
||||
display: block;
|
||||
font-weight: 300;
|
||||
}
|
||||
}
|
||||
}
|
||||
.appoptions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
gap: 5px;
|
||||
.optdetails {
|
||||
display: flex;
|
||||
.input {
|
||||
margin: 0 20px;
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
.optvalue {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
&.active {
|
||||
opacity: 1;
|
||||
width: auto;
|
||||
height: auto;
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
button.dark {
|
||||
background: #1b1b1b;
|
||||
border: none;
|
||||
padding: 12px 15px;
|
||||
border-radius: 4px;
|
||||
color: white;
|
||||
min-width: 240px;
|
||||
}
|
||||
}
|
||||
#app {
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
@@ -131,15 +191,31 @@ body {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
background: rgba(0,0,0,0.8);
|
||||
text-align: center;
|
||||
line-height: 50px;
|
||||
color: white;
|
||||
margin-top: 1px;
|
||||
position: relative;
|
||||
border: 1px solid transparent;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
img {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
.tooltip {
|
||||
bottom: 50%;
|
||||
left: auto;
|
||||
right: 55px;
|
||||
padding: 10px 15px;
|
||||
line-height: 1.2;
|
||||
transform: translate(200px, 50%);
|
||||
white-space: nowrap;
|
||||
&.active {
|
||||
transform: translate(0, 50%);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,6 +276,59 @@ body {
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
display: none;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
.tooltip {
|
||||
padding: 25px;
|
||||
border-radius: 5px;
|
||||
background: #000000c8;
|
||||
color: white;
|
||||
position: absolute;
|
||||
bottom: 120px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
font-size: 13px;
|
||||
backdrop-filter: blur(8px);
|
||||
z-index: 0;
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
transition: all 0.3s;
|
||||
&.active {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
z-index: 4;
|
||||
}
|
||||
}
|
||||
|
||||
.tile-actions {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0;
|
||||
padding: 7px;
|
||||
background: #000000d9;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
border-radius: 6px;
|
||||
width: 80px;
|
||||
height: 90px;
|
||||
display: flex;
|
||||
opacity: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.3s;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
&.active {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.refresh {
|
||||
z-index: 3;
|
||||
.icon {
|
||||
font-size: 20px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
.black {
|
||||
@@ -511,6 +640,15 @@ body {
|
||||
}
|
||||
}
|
||||
}
|
||||
.input {
|
||||
position: relative;
|
||||
.help {
|
||||
position: absolute;
|
||||
bottom: -22px;
|
||||
left: 10px;
|
||||
color: #c00;
|
||||
}
|
||||
}
|
||||
div.create {
|
||||
padding: 30px 15px;
|
||||
display: flex;
|
||||
@@ -534,10 +672,19 @@ div.create {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.app-icon-container {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-right: 15px;
|
||||
flex: 0 0 60px;
|
||||
}
|
||||
.app-icon {
|
||||
max-width: 60px;
|
||||
margin-right: 15px;
|
||||
display: block;
|
||||
max-height: 60px;
|
||||
}
|
||||
|
||||
.sidenav {
|
||||
@@ -576,6 +723,41 @@ div.create {
|
||||
color: #91a1b3;
|
||||
margin-left: 20px;
|
||||
}
|
||||
#websiteiconoptions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
.results {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px 0;
|
||||
}
|
||||
.selectclose {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.iconbutton {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.selecticon {
|
||||
max-width: 120px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.switch {
|
||||
position: relative;
|
||||
@@ -694,6 +876,8 @@ div.create {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
max-width: 620px;
|
||||
position: relative;
|
||||
z-index: 4;
|
||||
form {
|
||||
width: 100%;
|
||||
}
|
||||
@@ -784,7 +968,7 @@ div.create {
|
||||
|
||||
#appimage {
|
||||
img {
|
||||
max-width: 95px;
|
||||
width: 95px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -940,3 +1124,21 @@ select:-webkit-autofill:focus {
|
||||
transition: inherit;
|
||||
color: $app-text!important;
|
||||
}
|
||||
|
||||
#sortable:focus-within {
|
||||
.item:focus-within {
|
||||
outline: 1px solid #ffffff91;
|
||||
}
|
||||
.item:not(:focus-within) {
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
#config-buttons:focus-within {
|
||||
a:focus {
|
||||
outline: 0;
|
||||
border: 1px solid #ffffff91;
|
||||
}
|
||||
a:not(:focus-within) {
|
||||
opacity: 0.4;
|
||||
}
|
||||
}
|
||||
2
resources/assets/sass/app.scss
vendored
2
resources/assets/sass/app.scss
vendored
@@ -9,7 +9,7 @@
|
||||
@import "normalise";
|
||||
|
||||
// Bootstrap
|
||||
@import "app";
|
||||
@import "_app";
|
||||
@import "rune";
|
||||
|
||||
// Huebee
|
||||
|
||||
@@ -29,7 +29,6 @@ return [
|
||||
'settings.search' => 'busca',
|
||||
'settings.no_items' => 'Nenhum item encontrado',
|
||||
|
||||
|
||||
'settings.label' => 'Rótulo',
|
||||
'settings.value' => 'Valor',
|
||||
'settings.edit' => 'Editar',
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| App Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
*/
|
||||
|
||||
'settings.system' => '系统',
|
||||
'settings.appearance' => '外观',
|
||||
'settings.miscellaneous' => '其他',
|
||||
'settings.support' => '支持',
|
||||
'settings.donate' => '捐赠',
|
||||
|
||||
'settings.version' => '版本',
|
||||
'settings.background_image' => '背景图片',
|
||||
'settings.window_target' => '链接打开方式',
|
||||
'settings.window_target.current' => '在当前选项卡中打开',
|
||||
'settings.window_target.one' => '在同一个选项卡中打开',
|
||||
'settings.window_target.new' => '在新的选项卡中打开',
|
||||
'settings.homepage_search' => '主页搜索',
|
||||
'settings.search_provider' => '默认搜索引擎',
|
||||
'settings.language' => '语言',
|
||||
'settings.reset' => '重置为默认值',
|
||||
'settings.remove' => '删除',
|
||||
'settings.search' => '搜索',
|
||||
'settings.no_items' => '没有可用项目',
|
||||
|
||||
|
||||
'settings.label' => '设置项',
|
||||
'settings.value' => '内容',
|
||||
'settings.edit' => '编辑',
|
||||
'settings.view' => '查看',
|
||||
|
||||
'options.none' => '- 未设置 -',
|
||||
'options.google' => 'Google',
|
||||
'options.ddg' => 'DuckDuckGo',
|
||||
'options.bing' => 'Bing',
|
||||
'options.qwant' => 'Qwant',
|
||||
'options.startpage' => 'StartPage',
|
||||
'options.yes' => '是',
|
||||
'options.no' => '否',
|
||||
'options.nzbhydra' => 'NZBHydra',
|
||||
'options.jackett' => 'Jackett',
|
||||
|
||||
'buttons.save' => '保存',
|
||||
'buttons.cancel' => '取消',
|
||||
'buttons.add' => '添加',
|
||||
'buttons.upload' => '上传图标',
|
||||
'buttons.downloadapps' => '更新应用列表',
|
||||
|
||||
'dash.pin_item' => '将应用固定到仪表盘',
|
||||
'dash.no_apps' => '当前没有固定的应用, 请 :link1 或 :link2',
|
||||
'dash.link1' => '添加应用',
|
||||
'dash.link2' => '将应用固定到仪表盘',
|
||||
'dash.pinned_items' => '固定应用',
|
||||
|
||||
'apps.app_list' => '应用列表',
|
||||
'apps.view_trash' => '查看垃圾箱',
|
||||
'apps.add_application' => '添加应用',
|
||||
'apps.application_name' => '应用名称',
|
||||
'apps.colour' => '颜色',
|
||||
'apps.icon' => '图标',
|
||||
'apps.pinned' => '固定',
|
||||
'apps.title' => '标题',
|
||||
'apps.hex' => 'Hex颜色',
|
||||
'apps.username' => '用户名称',
|
||||
'apps.password' => '密码',
|
||||
'apps.config' => '配置',
|
||||
'apps.apikey' => 'API 密钥',
|
||||
'apps.enable' => 'Enable',
|
||||
'apps.tag_list' => '标签列表',
|
||||
'apps.add_tag' => '添加标签',
|
||||
'apps.tag_name' => '标签名称',
|
||||
'apps.tags' => '标签',
|
||||
'apps.override' => '如果与主链接不同',
|
||||
'apps.preview' => '预览',
|
||||
'apps.apptype' => '应用类型',
|
||||
|
||||
'dashboard' => '主页-控制台',
|
||||
|
||||
'user.user_list' => '用户',
|
||||
'user.add_user' => '添加用户',
|
||||
'user.username' => '用户名称',
|
||||
'user.avatar' => '头像',
|
||||
'user.email' => '邮箱地址',
|
||||
'user.password_confirm' => '重复密码',
|
||||
'user.secure_front' => '仅设置密码后才允许公开访问.',
|
||||
'user.autologin' => '仅可从特定的链接访问(任何通过链接都可访问).',
|
||||
|
||||
'url' => '链接',
|
||||
'title' => '标题',
|
||||
'delete' => '删除',
|
||||
'optional' => '可选',
|
||||
'restore' => '复位',
|
||||
|
||||
'alert.success.item_created' => '应用添加成功',
|
||||
'alert.success.item_updated' => '应用更新成功',
|
||||
'alert.success.item_deleted' => '应用删除成功',
|
||||
'alert.success.item_restored' => '应用复位成功',
|
||||
'alert.success.updating' => '更新应用列表完成',
|
||||
|
||||
'alert.success.tag_created' => '标签添加成功',
|
||||
'alert.success.tag_updated' => '标签更新成功',
|
||||
'alert.success.tag_deleted' => '标签删除成功',
|
||||
'alert.success.tag_restored' => '标签复位成功',
|
||||
|
||||
'alert.success.setting_updated' => '你已成功编辑此设置',
|
||||
'alert.error.not_exist' => '此设置项不存在.',
|
||||
|
||||
'alert.success.user_created' => '用户添加成功',
|
||||
'alert.success.user_updated' => '用户更新成功',
|
||||
'alert.success.user_deleted' => '用户删除成功',
|
||||
'alert.success.user_restored' => '用户复位成功',
|
||||
|
||||
|
||||
];
|
||||
106
resources/lang/cs/app.php
Normal file
106
resources/lang/cs/app.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
return array (
|
||||
'settings.system' => 'Systém',
|
||||
'settings.appearance' => 'Vzhled',
|
||||
'settings.miscellaneous' => 'Různé',
|
||||
'settings.advanced' => 'Rozšířené nastavení',
|
||||
'settings.support' => 'Podpora',
|
||||
'settings.donate' => 'Podpořte nás',
|
||||
'settings.version' => 'Verze',
|
||||
'settings.background_image' => 'Obrázek pozadí',
|
||||
'settings.window_target' => 'Odkazy otevírat v',
|
||||
'settings.window_target.current' => 'Otevřít v této záložce',
|
||||
'settings.window_target.one' => 'Otevřít ve stejné záložce',
|
||||
'settings.window_target.new' => 'Otevřít v nové záložce',
|
||||
'settings.homepage_search' => 'Vyhledávání na domovské stránce',
|
||||
'settings.search_provider' => 'Vyhledávat pomocí',
|
||||
'settings.language' => 'Jazyk',
|
||||
'settings.reset' => 'Obnovit výchozí nastavení',
|
||||
'settings.remove' => 'Odstranit',
|
||||
'settings.search' => 'hledat',
|
||||
'settings.no_items' => 'Žadné položky nenalezeny',
|
||||
'settings.label' => 'Název',
|
||||
'settings.value' => 'Hodnota',
|
||||
'settings.edit' => 'Upravit',
|
||||
'settings.view' => 'Náhled',
|
||||
'settings.custom_css' => 'Vlastní CSS',
|
||||
'settings.custom_js' => 'Vlastní JavaScript',
|
||||
'options.none' => '- nenastaveno -',
|
||||
'options.google' => 'Google',
|
||||
'options.ddg' => 'DuckDuckGo',
|
||||
'options.bing' => 'Bing',
|
||||
'options.qwant' => 'Qwant',
|
||||
'options.startpage' => 'StartPage',
|
||||
'options.yes' => 'Ano',
|
||||
'options.no' => 'Ne',
|
||||
'options.nzbhydra' => 'NZBHydra',
|
||||
'options.jackett' => 'Jackett',
|
||||
'buttons.save' => 'Uložit',
|
||||
'buttons.cancel' => 'Zrušit',
|
||||
'buttons.add' => 'Přidat',
|
||||
'buttons.upload' => 'Nahrát ikonu',
|
||||
'buttons.downloadapps' => 'Aktualizovat seznam aplikací',
|
||||
'dash.pin_item' => 'Připnout na dashboard',
|
||||
'dash.no_apps' => 'Aktuálně nemáte žádné připnuté aplikace, :link1 nebo :link2',
|
||||
'dash.link1' => 'Přidejte zde aplikacei',
|
||||
'dash.link2' => 'Připnout na dashboard',
|
||||
'dash.pinned_items' => 'Připnuté položky',
|
||||
'apps.app_list' => 'Seznam aplikací',
|
||||
'apps.view_trash' => 'Zobrazit koš',
|
||||
'apps.add_application' => 'Přidat aplikaci',
|
||||
'apps.application_name' => 'Název aplikace',
|
||||
'apps.colour' => 'Barva',
|
||||
'apps.icon' => 'Ikona',
|
||||
'apps.pinned' => 'Připnuto',
|
||||
'apps.title' => 'Název',
|
||||
'apps.hex' => 'Hex barva',
|
||||
'apps.username' => 'Uživatelské jméno',
|
||||
'apps.password' => 'Heslo',
|
||||
'apps.config' => 'Config',
|
||||
'apps.apikey' => 'API Klíč',
|
||||
'apps.enable' => 'Povolit',
|
||||
'apps.tag_list' => 'Seznam tagů',
|
||||
'apps.add_tag' => 'Přidat tag',
|
||||
'apps.tag_name' => 'Název tagu',
|
||||
'apps.tags' => 'Tagy',
|
||||
'apps.override' => 'Pokud je různá od hlavní url',
|
||||
'apps.preview' => 'Náhled',
|
||||
'apps.apptype' => 'Typ apliakce',
|
||||
'apps.website' => 'Webová stránka',
|
||||
'apps.description' => 'Popis',
|
||||
'apps.only_admin_account' => 'Pouze pokud máte administrátorský účet!',
|
||||
'apps.autologin_url' => 'URL automatického přihlášení',
|
||||
'apps.show_deleted' => 'Zobrazit smazané aplikace',
|
||||
'dashboard' => 'Domácí obrazovka',
|
||||
'user.user_list' => 'Uživatelé',
|
||||
'user.add_user' => 'Přidat uživatele',
|
||||
'user.username' => 'Uživatelské jméno',
|
||||
'user.avatar' => 'Avatar',
|
||||
'user.email' => 'Email',
|
||||
'user.password_confirm' => 'Potvrdit heslo',
|
||||
'user.secure_front' => 'Povolit veřejný přístup k rozhraní - Nastavte pouze pokud je nastaveno heslo.',
|
||||
'user.autologin' => 'Povolit přihlášení ze specifické URL. Kdokoliv s odkazem se může přihlásit.',
|
||||
'url' => 'URL',
|
||||
'title' => 'Název',
|
||||
'delete' => 'Smazat',
|
||||
'optional' => 'Volitelné',
|
||||
'restore' => 'Obnovit',
|
||||
'alert.success.item_created' => 'Položka úspěšně vytvořena',
|
||||
'alert.success.item_updated' => 'Položka úspěšně aktualizována',
|
||||
'alert.success.item_deleted' => 'Položka úspěšně smazána',
|
||||
'alert.success.item_restored' => 'Položka úspěšně obnovena',
|
||||
'alert.success.updating' => 'Aktualizuji seznam aplikací',
|
||||
'alert.success.tag_created' => 'Tag úspěšně vytvořen',
|
||||
'alert.success.tag_updated' => 'Tag úspěšně aktualizován',
|
||||
'alert.success.tag_deleted' => 'Tag úspěšně smazán',
|
||||
'alert.success.tag_restored' => 'Tag úspěšně obnoven',
|
||||
'alert.success.setting_updated' => 'Úspěšně jste aktualizovali nastavení',
|
||||
'alert.error.not_exist' => 'Tohle nastavení neexistuje.',
|
||||
'alert.success.user_created' => 'Uživatel úspěšně vytovřen',
|
||||
'alert.success.user_updated' => 'Uživatel úspěšně aktualizován',
|
||||
'alert.success.user_deleted' => 'Uživatel úspěšně smazán',
|
||||
'alert.success.user_restored' => 'Uživatel úspěšně obnoven',
|
||||
'dashboard.reorder' => 'Změňte pořadí a připněte položky',
|
||||
'dashboard.settings' => 'Nastavení',
|
||||
);
|
||||
6
resources/lang/cs/auth.php
Normal file
6
resources/lang/cs/auth.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return array (
|
||||
'failed' => 'Zadané údaje se neshodují s našimi záznamy.',
|
||||
'throttle' => 'Příliš mnoho pokusů o přihlášení. Prosím opakujte za :seconds sekund.',
|
||||
);
|
||||
6
resources/lang/cs/pagination.php
Normal file
6
resources/lang/cs/pagination.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return array (
|
||||
'previous' => '« Předchozí',
|
||||
'next' => 'Další »',
|
||||
);
|
||||
9
resources/lang/cs/passwords.php
Normal file
9
resources/lang/cs/passwords.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
return array (
|
||||
'password' => 'Heslo musí mít alespoň šest znaků a musí se shodovat s potvrzením.',
|
||||
'reset' => 'Vaše heslo bylo úspěšně resetováno!',
|
||||
'sent' => 'Odeslali jsme vám emailem odkaz pro reset hesla!',
|
||||
'token' => 'Token pro obnovu hesla je neplatný.',
|
||||
'user' => 'Nenalezli jsme uživatele se zadaným e-mailem.',
|
||||
);
|
||||
121
resources/lang/cs/validation.php
Normal file
121
resources/lang/cs/validation.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Validation Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines contain the default error messages used by
|
||||
| the validator class. Some of these rules have multiple versions such
|
||||
| as the size rules. Feel free to tweak each of these messages here.
|
||||
|
|
||||
*/
|
||||
|
||||
'accepted' => ':attribute musí být přijat.',
|
||||
'active_url' => ':attribute není platná URL.',
|
||||
'after' => ':attribute musí být datum po :date.',
|
||||
'after_or_equal' => ':attribute musí být datum po nebo rovno :date.',
|
||||
'alpha' => ':attribute může obsahovat pouze písmena.',
|
||||
'alpha_dash' => ':attribute může obsahovat pouze písmena, čísla a pomlčku.',
|
||||
'alpha_num' => ':attribute může obsahovat pouze písmena a čísla.',
|
||||
'array' => ':attribute musí být pole.',
|
||||
'before' => ':attribute musí být datum před :date.',
|
||||
'before_or_equal' => ':attribute musí být datum před nebo rovno :date.',
|
||||
'between' => [
|
||||
'numeric' => ':attribute musí být mezi :min a :max.',
|
||||
'file' => ':attribute musí být mezi :min a :max kilobyty.',
|
||||
'string' => ':attribute musí mít mezi :min a :max znaky.',
|
||||
'array' => ':attribute musí mít mezi :min a :max položkami.',
|
||||
],
|
||||
'boolean' => ':attribute může být true nebo false.',
|
||||
'confirmed' => ':attribute potvrzení se neshoduje.',
|
||||
'date' => ':attribute není platné datum.',
|
||||
'date_format' => ':attribute neodpovídá formátu :format.',
|
||||
'different' => ':attribute a :other se musí lišit.',
|
||||
'digits' => ':attribute musí být :digits číslo.',
|
||||
'digits_between' => ':attribute must be between :min and :max digits.',
|
||||
'dimensions' => ':attribute má neplatné rozměry.',
|
||||
'distinct' => ':attribute položka obsahuje duplicitní hodnoty.',
|
||||
'email' => ':attribute musí být platná emailová adresa.',
|
||||
'exists' => 'Vybraný :attribute je neplatný.',
|
||||
'file' => ':attribute musí být soubor.',
|
||||
'filled' => ':attribute položka musí mít hodnotu.',
|
||||
'image' => ':attribute musí být obrázek.',
|
||||
'in' => 'Vybraný :attribute je neplatný.',
|
||||
'in_array' => ':attribute položka neexistuje v :other.',
|
||||
'integer' => ':attribute musí být celočíselný.',
|
||||
'ip' => ':attribute musí být platná IP adresa.',
|
||||
'ipv4' => ':attribute musí být platná IPv4 adresa.',
|
||||
'ipv6' => ':attribute musí být platná IPv6 adresa.',
|
||||
'json' => ':attribute musí být validní JSON řetězec.',
|
||||
'max' => [
|
||||
'numeric' => ':attribute nemůže být větší než :max.',
|
||||
'file' => ':attribute nemůže být větší než :max kilobytů.',
|
||||
'string' => ':attribute nemůže být větší než :max znaků.',
|
||||
'array' => ':attribute nemsí mít více než :max položek.',
|
||||
],
|
||||
'mimes' => ':attribute musí být soubor typu: :values.',
|
||||
'mimetypes' => ':attribute musí být soubor typu: :values.',
|
||||
'min' => [
|
||||
'numeric' => ':attribute musí být nejméně :min.',
|
||||
'file' => ':attribute musí mít nejméně :min kilobytů.',
|
||||
'string' => ':attribute musí mít alespoň :min znaků.',
|
||||
'array' => ':attribute musí mít nejméně :min položek.',
|
||||
],
|
||||
'not_in' => 'Vybraný :attribute je neplatný.',
|
||||
'numeric' => ':attribute musí být číslo.',
|
||||
'present' => ':attribute musí být přitomná.',
|
||||
'regex' => ':attribute formát je neplatný.',
|
||||
'required' => ':attribute je povinná.',
|
||||
'required_if' => ':attribute je poviná pokud :other je :value.',
|
||||
'required_unless' => ':attribute je poviná pokud :other je v :values.',
|
||||
'required_with' => ':attribute je poviná pokud :values je přítomna.',
|
||||
'required_with_all' => ':attribute je poviná pokud :values je přítomna.',
|
||||
'required_without' => ':attribute je poviná pokud :values není přítomna.',
|
||||
'required_without_all' => ':attribute je poviná pokud žádná z :values není přítomná.',
|
||||
'same' => ':attribute a :other musí být stejné.',
|
||||
'size' => [
|
||||
'numeric' => ':attribute musí být :size.',
|
||||
'file' => ':attribute musí být :size kilobytes.',
|
||||
'string' => ':attribute musí být :size characters.',
|
||||
'array' => ':attribute musí obsahovat :size items.',
|
||||
],
|
||||
'string' => ':attribute musí být řetězec.',
|
||||
'timezone' => ':attribute musí být pltná časová zóna.',
|
||||
'unique' => ':attribute musí být unikátní.',
|
||||
'uploaded' => ':attribute se nepodařilo nahrát.',
|
||||
'url' => ':attribute formát je neplatný.',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Custom Validation Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify custom validation messages for attributes using the
|
||||
| convention "attribute.rule" to name the lines. This makes it quick to
|
||||
| specify a specific custom language line for a given attribute rule.
|
||||
|
|
||||
*/
|
||||
|
||||
'custom' => [
|
||||
'attribute-name' => [
|
||||
'rule-name' => 'custom-message',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Custom Validation Attributes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used to swap attribute place-holders
|
||||
| with something more reader friendly such as E-Mail Address instead
|
||||
| of "email". This simply helps us make messages a little cleaner.
|
||||
|
|
||||
*/
|
||||
|
||||
'attributes' => [],
|
||||
|
||||
];
|
||||
@@ -1,120 +1,106 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| App Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
*/
|
||||
|
||||
'settings.system' => 'System',
|
||||
'settings.appearance' => 'Appearance',
|
||||
'settings.miscellaneous' => 'Miscellaneous',
|
||||
'settings.support' => 'Support',
|
||||
'settings.donate' => 'Doner',
|
||||
|
||||
'settings.version' => 'Version',
|
||||
'settings.background_image' => 'Baggrundsbillede',
|
||||
'settings.window_target' => 'Link opens in',
|
||||
'settings.window_target.current' => 'Åbn i denne fane',
|
||||
'settings.window_target.one' => 'Åbn i den samme fane',
|
||||
'settings.window_target.new' => 'Åbn i en ny fane',
|
||||
'settings.homepage_search' => 'Homepage Search',
|
||||
'settings.search_provider' => 'Standardsøgemaskine',
|
||||
'settings.language' => 'Sprog',
|
||||
'settings.reset' => 'Nulstil tilbage til standard',
|
||||
'settings.remove' => 'Fjern',
|
||||
'settings.search' => 'søg',
|
||||
'settings.no_items' => 'Intet fundet',
|
||||
|
||||
|
||||
'settings.label' => 'Etiket',
|
||||
'settings.value' => 'Værdi',
|
||||
'settings.edit' => 'Rediger',
|
||||
'settings.view' => 'Vis',
|
||||
|
||||
'options.none' => '- ikke indstillet -',
|
||||
'options.google' => 'Google',
|
||||
'options.ddg' => 'DuckDuckGo',
|
||||
'options.bing' => 'Bing',
|
||||
'options.qwant' => 'Qwant',
|
||||
'options.startpage' => 'Startside',
|
||||
'options.yes' => 'Ja',
|
||||
'options.no' => 'Nej',
|
||||
'options.nzbhydra' => 'NZBHydra',
|
||||
'options.jackett' => 'Jackett',
|
||||
|
||||
'buttons.save' => 'Gem',
|
||||
'buttons.cancel' => 'Afbryd',
|
||||
'buttons.add' => 'Tilføj',
|
||||
'buttons.upload' => 'Upload et ikon',
|
||||
'buttons.downloadapps' => 'Opdater apps-listen',
|
||||
|
||||
'dash.pin_item' => 'Fastgør element til dashboard',
|
||||
'dash.no_apps' => 'Der er i øjeblikket ingen fastgjorte applikationer, :link1 eller :link2',
|
||||
'dash.link1' => 'Add an application here',
|
||||
'dash.link2' => 'Pin an item to the dash',
|
||||
'dash.pinned_items' => 'Fastgjorte elementer',
|
||||
|
||||
'apps.app_list' => 'Applikations liste',
|
||||
'apps.view_trash' => 'View trash',
|
||||
'apps.add_application' => 'Tilføj applikation',
|
||||
'apps.application_name' => 'Applikations navn',
|
||||
'apps.colour' => 'Farver',
|
||||
'apps.icon' => 'Ikon',
|
||||
'apps.pinned' => 'Fastgjort',
|
||||
'apps.title' => 'Titel',
|
||||
'apps.hex' => 'Hex farver',
|
||||
'apps.username' => 'brugernavn',
|
||||
'apps.password' => 'kodeord',
|
||||
'apps.config' => 'Config',
|
||||
'apps.apikey' => 'API nøgle',
|
||||
'apps.enable' => 'Aktiver',
|
||||
'apps.tag_list' => 'Tags liste',
|
||||
'apps.add_tag' => 'Tilføj tag',
|
||||
'apps.tag_name' => 'Tag navn',
|
||||
'apps.tags' => 'Tags',
|
||||
'apps.override' => 'Hvis det er anderledes end hovedwebadressen',
|
||||
'apps.preview' => 'Eksempel',
|
||||
'apps.apptype' => 'Applikationstype',
|
||||
|
||||
'dashboard' => 'Home dashboard',
|
||||
|
||||
'user.user_list' => 'Brugere',
|
||||
'user.add_user' => 'Tilføj bruger',
|
||||
'user.username' => 'Brugernavn',
|
||||
'user.avatar' => 'Avatar',
|
||||
'user.email' => 'E-mail',
|
||||
'user.password_confirm' => 'Bekræft kodeord',
|
||||
'user.secure_front' => 'Tillad offentlig adgang til forsiden - Kun håndhævet, hvis der er angivet en adgangskode.',
|
||||
'user.autologin' => 'Tillad at logge ind fra en bestemt URL. Alle med linket kan logge ind.',
|
||||
|
||||
'url' => 'URL',
|
||||
'title' => 'Title',
|
||||
'delete' => 'Slet',
|
||||
'optional' => 'Valgfri',
|
||||
'restore' => 'Genskab',
|
||||
|
||||
'alert.success.item_created' => 'Item created successfully',
|
||||
'alert.success.item_updated' => 'Item updated successfully',
|
||||
'alert.success.item_deleted' => 'Item deleted successfully',
|
||||
'alert.success.item_restored' => 'Item restored successfully',
|
||||
'alert.success.updating' => 'Updating apps list',
|
||||
|
||||
'alert.success.tag_created' => 'Tag oprettet med succes',
|
||||
'alert.success.tag_updated' => 'Tag opdateret med succes',
|
||||
'alert.success.tag_deleted' => 'Tag slettet med succes',
|
||||
'alert.success.tag_restored' => 'Tag genskabt med succes',
|
||||
|
||||
'alert.success.setting_updated' => 'You have successfully edited this setting',
|
||||
'alert.error.not_exist' => 'Denne indstilling findes ikke.',
|
||||
|
||||
'alert.success.user_created' => 'Bruger oprettet med succes',
|
||||
'alert.success.user_updated' => 'Bruger opdateret med succes',
|
||||
'alert.success.user_deleted' => 'Bruger slettet med succes',
|
||||
'alert.success.user_restored' => 'Bruger genskabt med succes',
|
||||
|
||||
|
||||
];
|
||||
return array (
|
||||
'settings.system' => 'System',
|
||||
'settings.appearance' => 'Appearance',
|
||||
'settings.miscellaneous' => 'Miscellaneous',
|
||||
'settings.advanced' => 'Fremskreden',
|
||||
'settings.support' => 'Support',
|
||||
'settings.donate' => 'Doner',
|
||||
'settings.version' => 'Version',
|
||||
'settings.background_image' => 'Baggrundsbillede',
|
||||
'settings.window_target' => 'Link opens in',
|
||||
'settings.window_target.current' => 'Åbn i denne fane',
|
||||
'settings.window_target.one' => 'Åbn i den samme fane',
|
||||
'settings.window_target.new' => 'Åbn i en ny fane',
|
||||
'settings.homepage_search' => 'Homepage Search',
|
||||
'settings.search_provider' => 'Standardsøgemaskine',
|
||||
'settings.language' => 'Sprog',
|
||||
'settings.reset' => 'Nulstil tilbage til standard',
|
||||
'settings.remove' => 'Fjern',
|
||||
'settings.search' => 'søg',
|
||||
'settings.no_items' => 'Intet fundet',
|
||||
'settings.label' => 'Etiket',
|
||||
'settings.value' => 'Værdi',
|
||||
'settings.edit' => 'Rediger',
|
||||
'settings.view' => 'Vis',
|
||||
'settings.custom_css' => 'Brugerdefineret CSS',
|
||||
'settings.custom_js' => 'Brugerdefineret JavaScript',
|
||||
'options.none' => '- ikke indstillet -',
|
||||
'options.google' => 'Google',
|
||||
'options.ddg' => 'DuckDuckGo',
|
||||
'options.bing' => 'Bing',
|
||||
'options.qwant' => 'Qwant',
|
||||
'options.startpage' => 'Startside',
|
||||
'options.yes' => 'Ja',
|
||||
'options.no' => 'Nej',
|
||||
'options.nzbhydra' => 'NZBHydra',
|
||||
'options.jackett' => 'Jackett',
|
||||
'buttons.save' => 'Gem',
|
||||
'buttons.cancel' => 'Afbryd',
|
||||
'buttons.add' => 'Tilføj',
|
||||
'buttons.upload' => 'Upload et ikon',
|
||||
'buttons.downloadapps' => 'Opdater apps-listen',
|
||||
'dash.pin_item' => 'Fastgør element til dashboard',
|
||||
'dash.no_apps' => 'Der er i øjeblikket ingen fastgjorte applikationer, :link1 eller :link2',
|
||||
'dash.link1' => 'Add an application here',
|
||||
'dash.link2' => 'Pin an item to the dash',
|
||||
'dash.pinned_items' => 'Fastgjorte elementer',
|
||||
'apps.app_list' => 'Applikations liste',
|
||||
'apps.view_trash' => 'View trash',
|
||||
'apps.add_application' => 'Tilføj applikation',
|
||||
'apps.application_name' => 'Applikations navn',
|
||||
'apps.colour' => 'Farver',
|
||||
'apps.icon' => 'Ikon',
|
||||
'apps.pinned' => 'Fastgjort',
|
||||
'apps.title' => 'Titel',
|
||||
'apps.hex' => 'Hex farver',
|
||||
'apps.username' => 'brugernavn',
|
||||
'apps.password' => 'kodeord',
|
||||
'apps.config' => 'Config',
|
||||
'apps.apikey' => 'API nøgle',
|
||||
'apps.enable' => 'Aktiver',
|
||||
'apps.tag_list' => 'Tags liste',
|
||||
'apps.add_tag' => 'Tilføj tag',
|
||||
'apps.tag_name' => 'Tag navn',
|
||||
'apps.tags' => 'Tags',
|
||||
'apps.override' => 'Hvis det er anderledes end hovedwebadressen',
|
||||
'apps.preview' => 'Eksempel',
|
||||
'apps.apptype' => 'Applikationstype',
|
||||
'apps.website' => 'Internet side',
|
||||
'apps.description' => 'Beskrivelse',
|
||||
'apps.only_admin_account' => 'Kun hvis du har en admin-konto!',
|
||||
'apps.autologin_url' => 'Auto login url',
|
||||
'apps.show_deleted' => 'Viser slettede applikationer',
|
||||
'dashboard' => 'Home dashboard',
|
||||
'user.user_list' => 'Brugere',
|
||||
'user.add_user' => 'Tilføj bruger',
|
||||
'user.username' => 'Brugernavn',
|
||||
'user.avatar' => 'Avatar',
|
||||
'user.email' => 'E-mail',
|
||||
'user.password_confirm' => 'Bekræft kodeord',
|
||||
'user.secure_front' => 'Tillad offentlig adgang til forsiden - Kun håndhævet, hvis der er angivet en adgangskode.',
|
||||
'user.autologin' => 'Tillad at logge ind fra en bestemt URL. Alle med linket kan logge ind.',
|
||||
'url' => 'URL',
|
||||
'title' => 'Title',
|
||||
'delete' => 'Slet',
|
||||
'optional' => 'Valgfri',
|
||||
'restore' => 'Genskab',
|
||||
'alert.success.item_created' => 'Item created successfully',
|
||||
'alert.success.item_updated' => 'Item updated successfully',
|
||||
'alert.success.item_deleted' => 'Item deleted successfully',
|
||||
'alert.success.item_restored' => 'Item restored successfully',
|
||||
'alert.success.updating' => 'Updating apps list',
|
||||
'alert.success.tag_created' => 'Tag oprettet med succes',
|
||||
'alert.success.tag_updated' => 'Tag opdateret med succes',
|
||||
'alert.success.tag_deleted' => 'Tag slettet med succes',
|
||||
'alert.success.tag_restored' => 'Tag genskabt med succes',
|
||||
'alert.success.setting_updated' => 'You have successfully edited this setting',
|
||||
'alert.error.not_exist' => 'Denne indstilling findes ikke.',
|
||||
'alert.success.user_created' => 'Bruger oprettet med succes',
|
||||
'alert.success.user_updated' => 'Bruger opdateret med succes',
|
||||
'alert.success.user_deleted' => 'Bruger slettet med succes',
|
||||
'alert.success.user_restored' => 'Bruger genskabt med succes',
|
||||
'dashboard.reorder' => 'Genbestil og fastgør varer',
|
||||
'dashboard.settings' => 'Indstillinger',
|
||||
);
|
||||
6
resources/lang/da/auth.php
Normal file
6
resources/lang/da/auth.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return array (
|
||||
'failed' => 'Disse legitimationsoplysninger stemmer ikke overens med vores optegnelser.',
|
||||
'throttle' => 'For mange loginforsøg. Prøv venligst igen om :sekunder sekunder.',
|
||||
);
|
||||
@@ -1,19 +1,6 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Pagination Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used by the paginator library to build
|
||||
| the simple pagination links. You are free to change them to anything
|
||||
| you want to customize your views to better match your application.
|
||||
|
|
||||
*/
|
||||
|
||||
'previous' => '« Tidligere',
|
||||
'next' => 'Næste »',
|
||||
|
||||
];
|
||||
return array (
|
||||
'previous' => '« Tidligere',
|
||||
'next' => 'Næste »',
|
||||
);
|
||||
@@ -1,22 +1,9 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Reset Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are the default lines which match reasons
|
||||
| that are given by the password broker for a password update attempt
|
||||
| has failed, such as for an invalid token or invalid new password.
|
||||
|
|
||||
*/
|
||||
|
||||
'password' => 'Adgangskoder skal bestå af mindst seks tegn og matche bekræftelsen.',
|
||||
'reset' => 'Din adgangskode er nulstillet!',
|
||||
'sent' => 'Vi har sendt dig en e-mail med et link til nulstilling af adgangskode!',
|
||||
'token' => 'Dit token er ikke gyldigt!',
|
||||
'user' => "Vi kan ikke finde en bruger med den e-mail-adresse.",
|
||||
|
||||
];
|
||||
return array (
|
||||
'password' => 'Adgangskoder skal bestå af mindst seks tegn og matche bekræftelsen.',
|
||||
'reset' => 'Din adgangskode er nulstillet!',
|
||||
'sent' => 'Vi har sendt dig en e-mail med et link til nulstilling af adgangskode!',
|
||||
'token' => 'Dit token er ikke gyldigt!',
|
||||
'user' => 'Vi kan ikke finde en bruger med den e-mail-adresse.',
|
||||
);
|
||||
@@ -4,8 +4,15 @@ return array (
|
||||
'settings.system' => 'System',
|
||||
'settings.appearance' => 'Aussehen',
|
||||
'settings.miscellaneous' => 'Sonstiges',
|
||||
'settings.advanced' => 'Erweitert',
|
||||
'settings.support' => 'Unterstütze',
|
||||
'settings.donate' => 'Spende',
|
||||
'settings.version' => 'Version',
|
||||
'settings.background_image' => 'Hintergrundbild',
|
||||
'settings.window_target' => 'Link öffnen in',
|
||||
'settings.window_target.current' => 'In diesem Tab öffnen',
|
||||
'settings.window_target.one' => 'Im selben Tab öffnen',
|
||||
'settings.window_target.new' => 'Im neuen Tab öffnen',
|
||||
'settings.homepage_search' => 'Startseite Sucheingabe',
|
||||
'settings.search_provider' => 'Suchanbieter',
|
||||
'settings.language' => 'Sprache',
|
||||
@@ -17,17 +24,23 @@ return array (
|
||||
'settings.value' => 'Wert',
|
||||
'settings.edit' => 'Bearbeiten',
|
||||
'settings.view' => 'Ansicht',
|
||||
'settings.custom_css' => 'Angepasstes CSS',
|
||||
'settings.custom_js' => 'Angepasstes JavaScript',
|
||||
'options.none' => '- nicht festgelegt -',
|
||||
'options.google' => 'Google',
|
||||
'options.ddg' => 'DuckDuckGo',
|
||||
'options.bing' => 'Bing',
|
||||
'options.qwant' => 'Qwant',
|
||||
'options.startpage' => 'StartSeite',
|
||||
'options.yes' => 'Ja',
|
||||
'options.no' => 'Nein',
|
||||
'options.nzbhydra' => 'NZBHydra',
|
||||
'options.jackett' => 'Jackett',
|
||||
'buttons.save' => 'Speichern',
|
||||
'buttons.cancel' => 'Abbrechen',
|
||||
'buttons.add' => 'Hinzufügen',
|
||||
'buttons.upload' => 'Hochladen einer Datei',
|
||||
'buttons.downloadapps' => 'Update der Anwendungsliste',
|
||||
'dash.pin_item' => 'Element auf dem Dashboard anheften',
|
||||
'dash.no_apps' => 'Derzeit gibt es keine angeheftete Anwendungen. :link1 oder :link2',
|
||||
'dash.link1' => 'Anwendung neu hinzufügen',
|
||||
@@ -45,7 +58,29 @@ return array (
|
||||
'apps.username' => 'Benutzername',
|
||||
'apps.password' => 'Passwort',
|
||||
'apps.config' => 'Konfiguration',
|
||||
'apps.apikey' => 'API Key',
|
||||
'apps.enable' => 'Aktivieren',
|
||||
'apps.tag_list' => 'Tags Liste',
|
||||
'apps.add_tag' => 'Tag hinzufügen',
|
||||
'apps.tag_name' => 'Tag Name',
|
||||
'apps.tags' => 'Tags',
|
||||
'apps.override' => 'Fals anders zur Haupt-URL',
|
||||
'apps.preview' => 'Vorschau',
|
||||
'apps.apptype' => 'Anwendungstyp',
|
||||
'apps.website' => 'Webseite',
|
||||
'apps.description' => 'Beschreibung',
|
||||
'apps.only_admin_account' => 'Nur mit Admin-Konto!',
|
||||
'apps.autologin_url' => 'Auto Login URL',
|
||||
'apps.show_deleted' => 'Gelöschte Anwendung anzeigen',
|
||||
'dashboard' => 'Home Dashboard',
|
||||
'user.user_list' => 'Nutzer',
|
||||
'user.add_user' => 'Nutzer hinzufügen',
|
||||
'user.username' => 'Benutzername',
|
||||
'user.avatar' => 'Avatar',
|
||||
'user.email' => 'Email',
|
||||
'user.password_confirm' => 'Passwort bestätigen',
|
||||
'user.secure_front' => 'Öffentlichen Zugang erlauben - Tritt nur bei gesetztem Passwort in kraft.',
|
||||
'user.autologin' => 'Anmelden von spezieller URL erlauben. Jeder mit diesem Link kann sich anmelden.',
|
||||
'url' => 'URL',
|
||||
'title' => 'Titel',
|
||||
'delete' => 'Löschen',
|
||||
@@ -55,6 +90,17 @@ return array (
|
||||
'alert.success.item_updated' => 'Element erfolgreich aktualisiert',
|
||||
'alert.success.item_deleted' => 'Element erfolgreich gelöscht',
|
||||
'alert.success.item_restored' => 'Element erfolgreich wiederhergestellt',
|
||||
'alert.success.updating' => 'Aktualisiere Anwendungsliste',
|
||||
'alert.success.tag_created' => 'Tag erfolgreich erstellt',
|
||||
'alert.success.tag_updated' => 'Tag erfolgreich aktualisiert',
|
||||
'alert.success.tag_deleted' => 'Tag erfolgreich gelöscht',
|
||||
'alert.success.tag_restored' => 'Tag erfolgreich wiederhergestellt',
|
||||
'alert.success.setting_updated' => 'Die Einstellungen wurden übernommen',
|
||||
'alert.error.not_exist' => 'Diese Einstellung existiert nicht.',
|
||||
'alert.success.user_created' => 'Nutzer erfolgreich erstellt',
|
||||
'alert.success.user_updated' => 'Nutzer erfolgreich aktualisiert',
|
||||
'alert.success.user_deleted' => 'Nutzer erfolgreich gelöscht',
|
||||
'alert.success.user_restored' => 'Nutzer erfolgreich wiederhergestellt',
|
||||
'dashboard.reorder' => 'Elemente neu anordnen und anheften',
|
||||
'dashboard.settings' => 'Einstellungen',
|
||||
);
|
||||
6
resources/lang/de/auth.php
Normal file
6
resources/lang/de/auth.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return array (
|
||||
'failed' => 'Diese Anmeldeinformationen stimmen nicht mit unseren Aufzeichnungen überein.',
|
||||
'throttle' => 'Zu viele Anmeldeversuche. Bitte versuchen Sie es in :Sekunden Sekunden erneut.',
|
||||
);
|
||||
6
resources/lang/de/pagination.php
Normal file
6
resources/lang/de/pagination.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return array (
|
||||
'previous' => '« Vorherige',
|
||||
'next' => 'Weiter »',
|
||||
);
|
||||
9
resources/lang/de/passwords.php
Normal file
9
resources/lang/de/passwords.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
return array (
|
||||
'password' => 'Passwörter müssen mindestens sechs Zeichen lang sein und mit der Bestätigung übereinstimmen.',
|
||||
'reset' => 'Dein Passwort wurde zurück gesetzt!',
|
||||
'sent' => 'Wir haben Ihren Link zum Zurücksetzen des Passworts per E-Mail gesendet!',
|
||||
'token' => 'Dieses Token zum Zurücksetzen des Passworts ist ungültig.',
|
||||
'user' => 'Wir können keinen Benutzer mit dieser E-Mail-Adresse finden.',
|
||||
);
|
||||
@@ -1,120 +1,106 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| App Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
*/
|
||||
|
||||
'settings.system' => 'Σύστημα',
|
||||
'settings.appearance' => 'Εμφάνιση',
|
||||
'settings.miscellaneous' => 'Λοιπά',
|
||||
'settings.support' => 'Υποστήριξη',
|
||||
'settings.donate' => 'Δωρεά',
|
||||
|
||||
'settings.version' => 'Έκδοση',
|
||||
'settings.background_image' => 'Εικόνα Παρασκηνίου',
|
||||
'settings.window_target' => 'Ο Σύνδεσμος ανοίγει σε',
|
||||
'settings.window_target.current' => 'Άνοιγμα σε αυτή την καρτέλα',
|
||||
'settings.window_target.one' => 'Άνοιγμα στην ίδια καρτέλα',
|
||||
'settings.window_target.new' => 'Άνοιγμα σε νέα καρτέλα',
|
||||
'settings.homepage_search' => 'Αναζήτηση στην Αρχική Σελίδα',
|
||||
'settings.search_provider' => 'Προεπιλεγμένος Πάροχος Αναζήτησης',
|
||||
'settings.language' => 'Γλώσσα',
|
||||
'settings.reset' => 'Επαναφορά πίσω στις προεπιλογές',
|
||||
'settings.remove' => 'Αφαίρεση',
|
||||
'settings.search' => 'αναζήτηση',
|
||||
'settings.no_items' => 'Δε βρεθηκαν αποτελέσματα',
|
||||
|
||||
|
||||
'settings.label' => 'Ετικέτα',
|
||||
'settings.value' => 'Τιμή',
|
||||
'settings.edit' => 'Επεξεργασία',
|
||||
'settings.view' => 'Προβολή',
|
||||
|
||||
'options.none' => '- μη ορισμένο -',
|
||||
'options.google' => 'Google',
|
||||
'options.ddg' => 'DuckDuckGo',
|
||||
'options.bing' => 'Bing',
|
||||
'options.qwant' => 'Qwant',
|
||||
'options.startpage' => 'StartPage',
|
||||
'options.yes' => 'Ναι',
|
||||
'options.no' => 'Όχι',
|
||||
'options.nzbhydra' => 'NZBHydra',
|
||||
'options.jackett' => 'Jackett',
|
||||
|
||||
'buttons.save' => 'Αποθήκευση',
|
||||
'buttons.cancel' => 'Ακύρωση',
|
||||
'buttons.add' => 'Προσθήκη',
|
||||
'buttons.upload' => 'Μεταφόρτωση ενός αρχείου',
|
||||
'buttons.downloadapps' => 'Ανανέωση Λίστας Εφαρμογών',
|
||||
|
||||
'dash.pin_item' => 'Καρφίτσωμα του αντικειμένου στο ταμπλό',
|
||||
'dash.no_apps' => 'Δεν υπάρχουν προς το παρόν καρφιτσωμένες εφαρμογές, :link1 ή :link2',
|
||||
'dash.link1' => 'Προσθήκη μίας εφαρμογής εδώ',
|
||||
'dash.link2' => 'Καρφίτσωμα ενός αντικειμένου στο ταμπλό',
|
||||
'dash.pinned_items' => 'Καρφιτσωμένα αντικείμενα',
|
||||
|
||||
'apps.app_list' => 'Λίστα Εφαρμογών',
|
||||
'apps.view_trash' => 'Εμφάνιση Απορριμμάτων',
|
||||
'apps.add_application' => 'Προσθήκη εφαρμογής',
|
||||
'apps.application_name' => 'Όνομα Εφαρμογής',
|
||||
'apps.colour' => 'Χρώμα',
|
||||
'apps.icon' => 'Εικονίδιο',
|
||||
'apps.pinned' => 'Καρφιτσωμένο',
|
||||
'apps.title' => 'Τίτλος',
|
||||
'apps.hex' => 'Hex χρώμα',
|
||||
'apps.username' => 'Όνομα χρήστη',
|
||||
'apps.password' => 'Κωδικός πρόσβασης',
|
||||
'apps.config' => 'Ρύθμιση',
|
||||
'apps.apikey' => 'Κλειδί API',
|
||||
'apps.enable' => 'Ενεργοποίηση',
|
||||
'apps.tag_list' => 'Λίστα Ετικετών',
|
||||
'apps.add_tag' => 'Προσθήκη ετικέτας',
|
||||
'apps.tag_name' => 'Όνομα Ετικέτας',
|
||||
'apps.tags' => 'Ετικέτες',
|
||||
'apps.override' => 'Αν διαφορετικό με το κύριο url',
|
||||
'apps.preview' => 'Προεπισκόπιση',
|
||||
'apps.apptype' => 'Τύπος Εφαρμογής',
|
||||
|
||||
'dashboard' => 'Αρχικό ταμπλό',
|
||||
|
||||
'user.user_list' => 'Χρήστες',
|
||||
'user.add_user' => 'Προσθήκη χρήστη',
|
||||
'user.username' => 'Όνομα χρήστη',
|
||||
'user.avatar' => 'Εικόνα χρήστη',
|
||||
'user.email' => 'Email',
|
||||
'user.password_confirm' => 'Επιβεβαίωση κωδικού πρόσβασης',
|
||||
'user.secure_front' => 'Χορήγηση δημόσιας πρόσβασης στο εμπρόσθιο τμήμα - Τίθεται σε ενέργεια μόνο εαν έχει ορισθεί κωδικός.',
|
||||
'user.autologin' => 'Χορήγηση πρόσβασης από ένα συγκεκριμένο URL. Οποιοσδήποτε με τον σύνδεσμο μπορεί να εισέρθει.',
|
||||
|
||||
'url' => 'URL',
|
||||
'title' => 'Τίτλος',
|
||||
'delete' => 'Διαγραφή',
|
||||
'optional' => 'Προεραιτικό',
|
||||
'restore' => 'Επαναφορά',
|
||||
|
||||
'alert.success.item_created' => 'Το αντικείμενο δημιουργήθηκε επιτυχώς',
|
||||
'alert.success.item_updated' => 'Το αντικείμενο ενημερώθηκε επιτυχώς',
|
||||
'alert.success.item_deleted' => 'Το αντικείμενο διαγράφηκε επιτυχώς',
|
||||
'alert.success.item_restored' => 'Το αντικείμενο επαναφέρθηκε επιτυχώς',
|
||||
'alert.success.updating' => 'Η λίστα των εφαρμογών ενημερώνεται',
|
||||
|
||||
'alert.success.tag_created' => 'Η ετικέτα δημιουργήθηκε επιτυχώ',
|
||||
'alert.success.tag_updated' => 'Η ετικέτα ενημερώθηκε επιτυχώς',
|
||||
'alert.success.tag_deleted' => 'Η ετικέτα διαγράφηκε επιτυχώς',
|
||||
'alert.success.tag_restored' => 'Η ετικέτα επαναφέρθηκε επιτυχώς',
|
||||
|
||||
'alert.success.setting_updated' => 'Επεξεργαστήκατε επιτυχώς αυτή τη ρύθμιση',
|
||||
'alert.error.not_exist' => 'Αυτή η ρύθμιση δεν υπάρχει.',
|
||||
|
||||
'alert.success.user_created' => 'Ο χρήστης δημιουργήθηκε επιτυχώς',
|
||||
'alert.success.user_updated' => 'Ο χρήστης ενημερώθηκε επιτυχώς',
|
||||
'alert.success.user_deleted' => 'Ο χρήστης διαγράφηκε επιτυχώς',
|
||||
'alert.success.user_restored' => 'Ο χρήστης επαναφέρθηκε επιτυχώς',
|
||||
|
||||
|
||||
];
|
||||
return array (
|
||||
'settings.system' => 'Σύστημα',
|
||||
'settings.appearance' => 'Εμφάνιση',
|
||||
'settings.miscellaneous' => 'Λοιπά',
|
||||
'settings.advanced' => 'Προχωρημένος',
|
||||
'settings.support' => 'Υποστήριξη',
|
||||
'settings.donate' => 'Δωρεά',
|
||||
'settings.version' => 'Έκδοση',
|
||||
'settings.background_image' => 'Εικόνα Παρασκηνίου',
|
||||
'settings.window_target' => 'Ο Σύνδεσμος ανοίγει σε',
|
||||
'settings.window_target.current' => 'Άνοιγμα σε αυτή την καρτέλα',
|
||||
'settings.window_target.one' => 'Άνοιγμα στην ίδια καρτέλα',
|
||||
'settings.window_target.new' => 'Άνοιγμα σε νέα καρτέλα',
|
||||
'settings.homepage_search' => 'Αναζήτηση στην Αρχική Σελίδα',
|
||||
'settings.search_provider' => 'Προεπιλεγμένος Πάροχος Αναζήτησης',
|
||||
'settings.language' => 'Γλώσσα',
|
||||
'settings.reset' => 'Επαναφορά πίσω στις προεπιλογές',
|
||||
'settings.remove' => 'Αφαίρεση',
|
||||
'settings.search' => 'αναζήτηση',
|
||||
'settings.no_items' => 'Δε βρεθηκαν αποτελέσματα',
|
||||
'settings.label' => 'Ετικέτα',
|
||||
'settings.value' => 'Τιμή',
|
||||
'settings.edit' => 'Επεξεργασία',
|
||||
'settings.view' => 'Προβολή',
|
||||
'settings.custom_css' => 'Προσαρμοσμένο CSS',
|
||||
'settings.custom_js' => 'Προσαρμοσμένη JavaScript',
|
||||
'options.none' => '- μη ορισμένο -',
|
||||
'options.google' => 'Google',
|
||||
'options.ddg' => 'DuckDuckGo',
|
||||
'options.bing' => 'Bing',
|
||||
'options.qwant' => 'Qwant',
|
||||
'options.startpage' => 'StartPage',
|
||||
'options.yes' => 'Ναι',
|
||||
'options.no' => 'Όχι',
|
||||
'options.nzbhydra' => 'NZBHydra',
|
||||
'options.jackett' => 'Jackett',
|
||||
'buttons.save' => 'Αποθήκευση',
|
||||
'buttons.cancel' => 'Ακύρωση',
|
||||
'buttons.add' => 'Προσθήκη',
|
||||
'buttons.upload' => 'Μεταφόρτωση ενός αρχείου',
|
||||
'buttons.downloadapps' => 'Ανανέωση Λίστας Εφαρμογών',
|
||||
'dash.pin_item' => 'Καρφίτσωμα του αντικειμένου στο ταμπλό',
|
||||
'dash.no_apps' => 'Δεν υπάρχουν προς το παρόν καρφιτσωμένες εφαρμογές, :link1 ή :link2',
|
||||
'dash.link1' => 'Προσθήκη μίας εφαρμογής εδώ',
|
||||
'dash.link2' => 'Καρφίτσωμα ενός αντικειμένου στο ταμπλό',
|
||||
'dash.pinned_items' => 'Καρφιτσωμένα αντικείμενα',
|
||||
'apps.app_list' => 'Λίστα Εφαρμογών',
|
||||
'apps.view_trash' => 'Εμφάνιση Απορριμμάτων',
|
||||
'apps.add_application' => 'Προσθήκη εφαρμογής',
|
||||
'apps.application_name' => 'Όνομα Εφαρμογής',
|
||||
'apps.colour' => 'Χρώμα',
|
||||
'apps.icon' => 'Εικονίδιο',
|
||||
'apps.pinned' => 'Καρφιτσωμένο',
|
||||
'apps.title' => 'Τίτλος',
|
||||
'apps.hex' => 'Hex χρώμα',
|
||||
'apps.username' => 'Όνομα χρήστη',
|
||||
'apps.password' => 'Κωδικός πρόσβασης',
|
||||
'apps.config' => 'Ρύθμιση',
|
||||
'apps.apikey' => 'Κλειδί API',
|
||||
'apps.enable' => 'Ενεργοποίηση',
|
||||
'apps.tag_list' => 'Λίστα Ετικετών',
|
||||
'apps.add_tag' => 'Προσθήκη ετικέτας',
|
||||
'apps.tag_name' => 'Όνομα Ετικέτας',
|
||||
'apps.tags' => 'Ετικέτες',
|
||||
'apps.override' => 'Αν διαφορετικό με το κύριο url',
|
||||
'apps.preview' => 'Προεπισκόπιση',
|
||||
'apps.apptype' => 'Τύπος Εφαρμογής',
|
||||
'apps.website' => 'Δικτυακός τόπος',
|
||||
'apps.description' => 'Περιγραφή',
|
||||
'apps.only_admin_account' => 'Μόνο αν έχετε λογαριασμό διαχειριστή!',
|
||||
'apps.autologin_url' => 'URL αυτόματης σύνδεσης',
|
||||
'apps.show_deleted' => 'Εμφάνιση διαγραμμένων εφαρμογών',
|
||||
'dashboard' => 'Αρχικό ταμπλό',
|
||||
'user.user_list' => 'Χρήστες',
|
||||
'user.add_user' => 'Προσθήκη χρήστη',
|
||||
'user.username' => 'Όνομα χρήστη',
|
||||
'user.avatar' => 'Εικόνα χρήστη',
|
||||
'user.email' => 'Email',
|
||||
'user.password_confirm' => 'Επιβεβαίωση κωδικού πρόσβασης',
|
||||
'user.secure_front' => 'Χορήγηση δημόσιας πρόσβασης στο εμπρόσθιο τμήμα - Τίθεται σε ενέργεια μόνο εαν έχει ορισθεί κωδικός.',
|
||||
'user.autologin' => 'Χορήγηση πρόσβασης από ένα συγκεκριμένο URL. Οποιοσδήποτε με τον σύνδεσμο μπορεί να εισέρθει.',
|
||||
'url' => 'URL',
|
||||
'title' => 'Τίτλος',
|
||||
'delete' => 'Διαγραφή',
|
||||
'optional' => 'Προεραιτικό',
|
||||
'restore' => 'Επαναφορά',
|
||||
'alert.success.item_created' => 'Το αντικείμενο δημιουργήθηκε επιτυχώς',
|
||||
'alert.success.item_updated' => 'Το αντικείμενο ενημερώθηκε επιτυχώς',
|
||||
'alert.success.item_deleted' => 'Το αντικείμενο διαγράφηκε επιτυχώς',
|
||||
'alert.success.item_restored' => 'Το αντικείμενο επαναφέρθηκε επιτυχώς',
|
||||
'alert.success.updating' => 'Η λίστα των εφαρμογών ενημερώνεται',
|
||||
'alert.success.tag_created' => 'Η ετικέτα δημιουργήθηκε επιτυχώ',
|
||||
'alert.success.tag_updated' => 'Η ετικέτα ενημερώθηκε επιτυχώς',
|
||||
'alert.success.tag_deleted' => 'Η ετικέτα διαγράφηκε επιτυχώς',
|
||||
'alert.success.tag_restored' => 'Η ετικέτα επαναφέρθηκε επιτυχώς',
|
||||
'alert.success.setting_updated' => 'Επεξεργαστήκατε επιτυχώς αυτή τη ρύθμιση',
|
||||
'alert.error.not_exist' => 'Αυτή η ρύθμιση δεν υπάρχει.',
|
||||
'alert.success.user_created' => 'Ο χρήστης δημιουργήθηκε επιτυχώς',
|
||||
'alert.success.user_updated' => 'Ο χρήστης ενημερώθηκε επιτυχώς',
|
||||
'alert.success.user_deleted' => 'Ο χρήστης διαγράφηκε επιτυχώς',
|
||||
'alert.success.user_restored' => 'Ο χρήστης επαναφέρθηκε επιτυχώς',
|
||||
'dashboard.reorder' => 'Παραγγείλετε ξανά και καρφιτσώστε αντικείμενα',
|
||||
'dashboard.settings' => 'Ρυθμίσεις',
|
||||
);
|
||||
@@ -1,19 +1,6 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used during authentication for various
|
||||
| messages that we need to display to the user. You are free to modify
|
||||
| these language lines according to your application's requirements.
|
||||
|
|
||||
*/
|
||||
|
||||
'failed' => 'Αυτά τα διαπιστευτήρια δεν ταιριάζουν με τα μητρώα μας.',
|
||||
'throttle' => 'Πολλές προσπάθειες εισόδου. Παρακαλούμε προσπαθήστε ξανά σε :seconds δευτερόλεπτα.',
|
||||
|
||||
];
|
||||
return array (
|
||||
'failed' => 'Αυτά τα διαπιστευτήρια δεν ταιριάζουν με τα μητρώα μας.',
|
||||
'throttle' => 'Πολλές προσπάθειες εισόδου. Παρακαλούμε προσπαθήστε ξανά σε :seconds δευτερόλεπτα.',
|
||||
);
|
||||
@@ -1,19 +1,6 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Pagination Language Lines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following language lines are used by the paginator library to build
|
||||
| the simple pagination links. You are free to change them to anything
|
||||
| you want to customize your views to better match your application.
|
||||
|
|
||||
*/
|
||||
|
||||
'previous' => '« Προηγούμενη',
|
||||
'next' => 'Επόμενη »',
|
||||
|
||||
];
|
||||
return array (
|
||||
'previous' => '« Προηγούμενη',
|
||||
'next' => 'Επόμενη »',
|
||||
);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user