chore: use Laravel' original structure

This commit is contained in:
Phan An 2020-09-12 17:01:48 +02:00
parent 8c7ea708a5
commit 860ec4648f
32 changed files with 98 additions and 134 deletions

View file

@ -1,3 +1,3 @@
FROM gitpod/workspace-mysql:latest
ENV APACHE_DOCROOT_IN_REPO=""
ENV APACHE_DOCROOT_IN_REPO="public"

View file

@ -2163,7 +2163,7 @@ fetch(url, {
<p>Example response (200):</p>
</blockquote>
<pre><code class="language-json">{
"artistUrl": "https:\/\/koel.host\/images\/artists\/new-cover.jpg"
"artistUrl": "https:\/\/koel.host\/img\/artists\/new-cover.jpg"
}</code></pre>
<h3>HTTP Request</h3>
<p><code>PUT api/artist/{artist}/image</code></p>
@ -3855,4 +3855,4 @@ fetch(url, {
</div>
</div>
</body>
</html>
</html>

View file

@ -2236,7 +2236,7 @@ fetch(url, {
```json
{
"artistUrl": "https:\/\/koel.host\/images\/artists\/new-cover.jpg"
"artistUrl": "https:\/\/koel.host\/img\/artists\/new-cover.jpg"
}
```

View file

@ -17,16 +17,6 @@ class Application extends IlluminateApplication
*/
public const KOEL_VERSION = 'v4.4.0';
/**
* We have merged public path and base path.
*
* @return string
*/
public function publicPath()
{
return $this->basePath;
}
/**
* Loads a revision'ed asset file, making use of gulp-rev
* This is a copycat of L5's Elixir, but catered to our directory structure.
@ -37,16 +27,16 @@ class Application extends IlluminateApplication
{
static $manifest = null;
$manifestFile = $manifestFile ?: public_path('public/mix-manifest.json');
$manifestFile = $manifestFile ?: public_path('mix-manifest.json');
if ($manifest === null) {
$manifest = json_decode(file_get_contents($manifestFile), true);
}
if (isset($manifest[$file])) {
return file_exists(public_path('public/hot'))
? "http://localhost:8080/public{$manifest[$file]}"
: $this->staticUrl("public{$manifest[$file]}");
return file_exists(public_path('hot'))
? "http://localhost:8080{$manifest[$file]}"
: $this->staticUrl("{$manifest[$file]}");
}
throw new InvalidArgumentException("File {$file} not defined in asset manifest.");

View file

@ -24,7 +24,7 @@ class AlbumThumbnailController extends Controller
* Get an album's thumbnail (a 48px-wide blurry version of the album's cover).
* Returns the full URL to the thumbnail or NULL if the album has no cover.
*
* @response ["thumbnailUrl", "https://localhost/public/img/covers/a146d01afb742b01f28ab8b556f9a75d_thumbnail.jpg"]
* @response ["thumbnailUrl", "https://localhost/img/covers/a146d01afb742b01f28ab8b556f9a75d_thumbnail.jpg"]
*/
public function get(Album $album): JsonResponse
{

View file

@ -21,7 +21,7 @@ class RedirectIfAuthenticated
public function handle(Request $request, Closure $next)
{
if ($this->auth->check()) {
return redirect('/');
return redirect('/');
}
return $next($request);

View file

@ -1,25 +0,0 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
/**
* Check if the app is running in an E2E session and use the proper data settings.
*/
class UseDifferentConfigIfE2E
{
/**
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
if (Arr::get($_SERVER, 'SERVER_PORT') === '8081') {
config(['database.default' => 'sqlite-e2e']);
}
return $next($request);
}
}

View file

@ -11,7 +11,7 @@
|
*/
$app = new App\Application(__DIR__.'/../');
$app = new App\Application(dirname(__DIR__));
/*
|--------------------------------------------------------------------------

View file

@ -1,7 +1,5 @@
<?php
define('LARAVEL_START', microtime(true));
/*
|--------------------------------------------------------------------------
| Register The Composer Auto Loader

View file

@ -19,10 +19,10 @@ return [
'media_path' => env('MEDIA_PATH'),
// The *relative* path to the directory to store album covers and thumbnails, *with* a trailing slash.
'album_cover_dir' => 'public/img/covers/',
'album_cover_dir' => 'img/covers/',
// The *relative* path to the directory to store artist images, *with* a trailing slash.
'artist_image_dir' => 'public/img/artists/',
'artist_image_dir' => 'img/artists/',
/*
|--------------------------------------------------------------------------

View file

@ -1,18 +1,13 @@
server {
listen *:80;
server_name koel.dev;
root /var/www/koel;
root /var/www/koel/public;
index index.php;
gzip on;
gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript application/json;
gzip_comp_level 9;
# Whitelist only index.php, robots.txt, and some special routes
if ($request_uri !~ ^/$|index\.php|robots\.txt|(public|api|web)/|remote|api-docs|sw\.js) {
return 404;
}
location /media/ {
internal;

12
public/.gitignore vendored
View file

@ -1,5 +1,7 @@
*
!.gitignore
!manifest.json.example
!manifest-remote.json.example
!browserconfig.xml
css
fonts
img
js
manifest.json
manifest-remote.json
hot

View file

@ -6,26 +6,24 @@
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
RewriteBase /
# Redirect Trailing Slashes...
RewriteRule ^(.*)/$ /$1 [L,R=301]
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Whitelist only index.php, robots.txt, and some special routes
RewriteRule ^(?!($|index\.php|robots\.txt|(public|api|web)/|remote|api-docs|sw\.js)) - [R=404,L]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* index.php [L]
# https://github.com/tymondesigns/jwt-auth/wiki/Authentication
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
RewriteRule ^ index.php [L]
</IfModule>
<IfModule mod_expires.c>
@ -52,7 +50,7 @@
<IfModule mod_deflate.c>
# Disable deflation for media files.
SetEnvIfNoCase Request_URI "^/api/play/" no-gzip dont-vary
SetEnvIfNoCase Request_URI "^/play/" no-gzip dont-vary
# ----------------------------------------------------------------------
# Gzip compression.

View file

@ -3,10 +3,10 @@
<browserconfig>
<msapplication>
<tile>
<square70x70logo src="public/img/tile.png"/>
<square150x150logo src="public/img/tile.png"/>
<wide310x150logo src="public/img/tile-wide.png"/>
<square310x310logo src="public/img/tile.png"/>
<square70x70logo src="img/tile.png"/>
<square150x150logo src="img/tile.png"/>
<wide310x150logo src="img/tile-wide.png"/>
<square310x310logo src="img/tile.png"/>
</tile>
</msapplication>
</browserconfig>

View file

@ -18,7 +18,12 @@
|
*/
require __DIR__.'/bootstrap/autoload.php';
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Http\Request;
define('LARAVEL_START', microtime(true));
require __DIR__.'/../bootstrap/autoload.php';
/*
|--------------------------------------------------------------------------
@ -32,7 +37,7 @@ require __DIR__.'/bootstrap/autoload.php';
|
*/
$app = require_once __DIR__.'/bootstrap/app.php';
$app = require_once __DIR__.'/../bootstrap/app.php';
/*
|--------------------------------------------------------------------------
@ -46,12 +51,10 @@ $app = require_once __DIR__.'/bootstrap/app.php';
|
*/
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$kernel = $app->make(Kernel::class);
$response = $kernel->handle(
$request = Illuminate\Http\Request::capture()
);
$response->send();
$response = tap($kernel->handle(
$request = Request::capture()
))->send();
$kernel->terminate($request, $response);

View file

@ -4,7 +4,7 @@
"display": "standalone",
"orientation": "portrait",
"icons": [{
"src": "/public/img/icon.png",
"src": "/img/icon.png",
"sizes": "192x192",
"type": "image/png"
}],

View file

@ -4,7 +4,7 @@
"display": "standalone",
"orientation": "portrait",
"icons": [{
"src": "/public/img/icon.png",
"src": "/img/icon.png",
"sizes": "192x192",
"type": "image/png"
}],

6
public/mix-manifest.json Normal file
View file

@ -0,0 +1,6 @@
{
"/js/app.js": "/js/app.js",
"/css/app.css": "/css/app.css",
"/css/remote.css": "/css/remote.css",
"/js/remote/app.js": "/js/remote/app.js"
}

View file

View file

@ -12,11 +12,11 @@
<meta name="msapplication-navbutton-color" content="#282828">
<base href="{{ asset('') }}">
<link rel="manifest" href="{{ App::staticUrl('public/manifest.json') }}" />
<meta name="msapplication-config" content="{{ App::staticUrl('public/browserconfig.xml') }}" />
<link rel="icon" type="image/x-icon" href="{{ App::staticUrl('public/img/favicon.ico') }}" />
<link rel="icon" href="{{ App::staticUrl('public/img/icon.png') }}">
<link rel="apple-touch-icon" href="{{ App::staticUrl('public/img/icon.png') }}">
<link rel="manifest" href="{{ App::staticUrl('manifest.json') }}" />
<meta name="msapplication-config" content="{{ App::staticUrl('browserconfig.xml') }}" />
<link rel="icon" type="image/x-icon" href="{{ App::staticUrl('img/favicon.ico') }}" />
<link rel="icon" href="{{ App::staticUrl('img/icon.png') }}">
<link rel="apple-touch-icon" href="{{ App::staticUrl('img/icon.png') }}">
<link rel="stylesheet" href="{{ App::rev('/css/app.css') }}">
</head>

View file

@ -13,11 +13,11 @@
<meta name="msapplication-navbutton-color" content="#282828">
<base href="{{ asset('') }}">
<link rel="manifest" href="{{ App::staticUrl('public/manifest-remote.json') }}" />
<meta name="msapplication-config" content="{{ App::staticUrl('public/browserconfig.xml') }}" />
<link rel="icon" type="image/x-icon" href="{{ App::staticUrl('public/img/favicon.ico') }}" />
<link rel="icon" href="{{ App::staticUrl('public/img/icon.png') }}">
<link rel="apple-touch-icon" href="{{ App::staticUrl('public/img/icon.png') }}">
<link rel="manifest" href="{{ App::staticUrl('manifest-remote.json') }}" />
<meta name="msapplication-config" content="{{ App::staticUrl('browserconfig.xml') }}" />
<link rel="icon" type="image/x-icon" href="{{ App::staticUrl('img/favicon.ico') }}" />
<link rel="icon" href="{{ App::staticUrl('img/icon.png') }}">
<link rel="apple-touch-icon" href="{{ App::staticUrl('img/icon.png') }}">
<link rel="stylesheet" href="{{ App::rev('/css/remote.css') }}">
</head>

View file

@ -11,8 +11,8 @@ Route::get('/remote', static function () {
return view('remote');
});
Route::group(['middleware' => 'auth', 'prefix' => 'web'], static function (): void {
Route::get('/{song}/play/{transcode?}/{bitrate?}', 'PlayController@show')
Route::group(['middleware' => 'auth'], static function (): void {
Route::get('play/{song}/{transcode?}/{bitrate?}', 'PlayController@show')
->name('song.play');
Route::group(['prefix' => 'lastfm'], static function (): void {

View file

@ -12,8 +12,8 @@ $uri = urldecode(
// This file allows us to emulate Apache's "mod_rewrite" functionality from the
// built-in PHP web server. This provides a convenient way to test a Laravel
// application without having installed a "real" web server software here.
if ($uri !== '/' && file_exists(__DIR__.$uri)) {
if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) {
return false;
}
require_once __DIR__.'/index.php';
require_once __DIR__.'/public/index.php';

View file

@ -1,3 +1,3 @@
{
"coverUrl": "https://koel.host/images/albums/new-cover.jpg"
"coverUrl": "https://koel.host/img/albums/new-cover.jpg"
}

View file

@ -1,3 +1,3 @@
{
"imageUrl": "https://koel.host/images/artists/new-cover.jpg"
"imageUrl": "https://koel.host/img/artists/new-cover.jpg"
}

View file

@ -18,7 +18,7 @@ class AlbumThumbnailTest extends TestCase
public function provideAlbumThumbnailData(): array
{
return [['http://localhost/public/img/covers/foo_thumbnail.jpg'], [null]];
return [['http://localhost/img/covers/foo_thumbnail.jpg'], [null]];
}
/** @dataProvider provideAlbumThumbnailData */

View file

@ -41,7 +41,7 @@ class DownloadTest extends TestCase
->shouldReceive('from')
->never();
$this->get("web/download/songs?songs[]={$song->id}")
$this->get("download/songs?songs[]={$song->id}")
->assertRedirect('/');
}
@ -60,7 +60,7 @@ class DownloadTest extends TestCase
}))
->andReturn($this->mediaPath.'/blank.mp3');
$this->get("web/download/songs?songs[]={$song->id}&api_token=".$user->createToken('Koel')->plainTextToken)
$this->get("download/songs?songs[]={$song->id}&api_token=".$user->createToken('Koel')->plainTextToken)
->assertOk();
}
@ -83,7 +83,7 @@ class DownloadTest extends TestCase
->andReturn($this->mediaPath.'/blank.mp3'); // should be a zip file, but we're testing here…
$this->get(
"web/download/songs?songs[]={$songs[0]->id}&songs[]={$songs[1]->id}&api_token="
"download/songs?songs[]={$songs[0]->id}&songs[]={$songs[1]->id}&api_token="
.$user->createToken('Koel')->plainTextToken
)
->assertOk();
@ -104,7 +104,7 @@ class DownloadTest extends TestCase
}))
->andReturn($this->mediaPath.'/blank.mp3');
$this->get("web/download/album/{$album->id}?api_token=".$user->createToken('Koel')->plainTextToken)
$this->get("download/album/{$album->id}?api_token=".$user->createToken('Koel')->plainTextToken)
->assertOk();
}
@ -123,7 +123,7 @@ class DownloadTest extends TestCase
}))
->andReturn($this->mediaPath.'/blank.mp3');
$this->get("web/download/artist/{$artist->id}?api_token=".$user->createToken('Koel')->plainTextToken)
$this->get("download/artist/{$artist->id}?api_token=".$user->createToken('Koel')->plainTextToken)
->assertOk();
}
@ -145,7 +145,7 @@ class DownloadTest extends TestCase
->once()
->andReturn($this->mediaPath.'/blank.mp3');
$this->get("web/download/playlist/{$playlist->id}?api_token=".$user->createToken('Koel')->plainTextToken)
$this->get("download/playlist/{$playlist->id}?api_token=".$user->createToken('Koel')->plainTextToken)
->assertOk();
}
@ -157,7 +157,7 @@ class DownloadTest extends TestCase
/** @var User $user */
$user = factory(User::class)->create();
$this->get("web/download/playlist/{$playlist->id}?api_token=".$user->createToken('Koel')->plainTextToken)
$this->get("download/playlist/{$playlist->id}?api_token=".$user->createToken('Koel')->plainTextToken)
->assertStatus(Response::HTTP_FORBIDDEN);
}
@ -181,7 +181,7 @@ class DownloadTest extends TestCase
->once()
->andReturn($this->mediaPath.'/blank.mp3');
$this->get('web/download/favorites?api_token='.$user->createToken('Koel')->plainTextToken)
$this->get('download/favorites?api_token='.$user->createToken('Koel')->plainTextToken)
->assertOk();
}
}

View file

@ -56,9 +56,9 @@ class LastfmTest extends TestCase
->with($user)
->andReturn($temporaryToken);
$this->get('web/lastfm/connect?api_token='.$token)
$this->get('lastfm/connect?api_token='.$token)
->assertRedirect(
'https://www.last.fm/api/auth/?api_key=foo&cb=http%3A%2F%2Flocalhost%2Fweb%2Flastfm%2Fcallback%3Fapi_token%3Dtmp-token'
'https://www.last.fm/api/auth/?api_key=foo&cb=http%3A%2F%2Flocalhost%2Flastfm%2Fcallback%3Fapi_token%3Dtmp-token'
);
}
@ -77,7 +77,7 @@ class LastfmTest extends TestCase
->once()
->andReturn('my-session-key');
$this->get('web/lastfm/callback?token=lastfm-token&api_token='.urlencode($token))
$this->get('lastfm/callback?token=lastfm-token&api_token='.urlencode($token))
->assertOk();
self::assertSame('my-session-key', $user->refresh()->lastfm_session_key);
@ -102,7 +102,7 @@ class LastfmTest extends TestCase
->with('my-token')
->andReturn($user);
$this->get('web/lastfm/callback?token=foo&api_token=my-token');
$this->get('lastfm/callback?token=foo&api_token=my-token');
self::assertEquals('bar', $user->refresh()->lastfm_session_key);
}

View file

@ -8,15 +8,15 @@ trait SandboxesTests
{
private static function createSandbox(): void
{
config(['koel.album_cover_dir' => 'public/sandbox/img/covers/']);
config(['koel.artist_image_dir' => 'public/sandbox/img/artists/']);
config(['koel.album_cover_dir' => 'sandbox/img/covers/']);
config(['koel.artist_image_dir' => 'sandbox/img/artists/']);
@mkdir(base_path(config('koel.album_cover_dir')), 0755, true);
@mkdir(base_path(config('koel.artist_image_dir')), 0755, true);
@mkdir(public_path(config('koel.album_cover_dir')), 0755, true);
@mkdir(public_path(config('koel.artist_image_dir')), 0755, true);
}
private static function destroySandbox(): void
{
File::deleteDirectory(base_path('public/sandbox'));
File::deleteDirectory(public_path('sandbox'));
}
}

View file

@ -9,7 +9,8 @@ class ApplicationTest extends TestCase
public function setUp(): void
{
parent::setUp();
@unlink(app()->publicPath().'/public/hot');
@unlink(public_path('hot'));
}
/** @test */
@ -55,7 +56,7 @@ class ApplicationTest extends TestCase
$assetURL = app()->rev('/foo.css', $manifestFile);
// Then I see they're constructed correctly
self::assertEquals('http://localhost/public/foo00.css', $assetURL);
self::assertEquals('http://localhost/foo00.css', $assetURL);
}
/** @test */
@ -71,6 +72,6 @@ class ApplicationTest extends TestCase
$assetURL = app()->rev('/foo.css', $manifestFile);
// Then I see they're constructed correctly
self::assertEquals('http://cdn.tld/public/foo00.css', $assetURL);
self::assertEquals('http://cdn.tld/foo00.css', $assetURL);
}
}

View file

@ -34,12 +34,12 @@ class MediaMetadataServiceTest extends TestCase
/** @var Album $album */
$album = factory(Album::class)->create();
$coverContent = 'dummy';
$coverPath = '/koel/public/images/album/foo.jpg';
$coverPath = '/koel/public/img/album/foo.jpg';
$this->imageWriter
->shouldReceive('writeFromBinaryData')
->once()
->with('/koel/public/images/album/foo.jpg', 'dummy');
->with('/koel/public/img/album/foo.jpg', 'dummy');
$this->mediaMetadataService->writeAlbumCover($album, $coverContent, 'jpg', $coverPath);
self::assertEquals(album_cover_url('foo.jpg'), Album::find($album->id)->cover);
@ -50,12 +50,12 @@ class MediaMetadataServiceTest extends TestCase
/** @var Artist $artist */
$artist = factory(Artist::class)->create();
$imageContent = 'dummy';
$imagePath = '/koel/public/images/artist/foo.jpg';
$imagePath = '/koel/public/img/artist/foo.jpg';
$this->imageWriter
->shouldReceive('writeFromBinaryData')
->once()
->with('/koel/public/images/artist/foo.jpg', 'dummy');
->with('/koel/public/img/artist/foo.jpg', 'dummy');
$this->mediaMetadataService->writeArtistImage($artist, $imageContent, 'jpg', $imagePath);
self::assertEquals(artist_image_url('foo.jpg'), Artist::find($artist->id)->image);

View file

@ -8,7 +8,7 @@ mix.webpackConfig({
plugins,
output: {
chunkFilename: mix.config.production ? 'js/[name].[chunkhash].js' : 'js/[name].js',
publicPath: '/public/'
publicPath: '/'
},
devServer: {
port: 8080,
@ -18,13 +18,9 @@ mix.webpackConfig({
}
})
mix.setResourceRoot('./public/')
mix.setResourceRoot('./')
if (mix.config.hmr) {
// There's a bug with Mix/copy plugin which prevents HMR from working:
// https://github.com/JeffreyWay/laravel-mix/issues/150
console.log('In HMR mode. If assets are missing, Ctr+C and run `yarn dev` first.')
// Somehow public/hot isn't being removed by Mix. We'll handle it ourselves.
process.on('SIGINT', () => {
try {