From ec3fbeac58a1e42308be0e6555cb6f5ad93fe59e Mon Sep 17 00:00:00 2001 From: Simon Date: Sat, 15 Aug 2020 00:35:51 +0200 Subject: [PATCH 01/80] Laravel Passport initial --- app/Providers/AuthServiceProvider.php | 5 +- app/User.php | 4 +- composer.json | 1 + composer.lock | 976 ++++- config/auth.php | 2 +- package.json | 2 +- public/js/app.js | 3190 ++++++++++++++++- resources/js/app.js | 15 + .../components/passport/AuthorizedClients.vue | 107 + resources/js/components/passport/Clients.vue | 416 +++ .../passport/PersonalAccessTokens.vue | 298 ++ resources/views/home.blade.php | 12 +- 12 files changed, 4972 insertions(+), 56 deletions(-) create mode 100644 resources/js/components/passport/AuthorizedClients.vue create mode 100644 resources/js/components/passport/Clients.vue create mode 100644 resources/js/components/passport/PersonalAccessTokens.vue diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 30490683..a2b0a77a 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -4,6 +4,7 @@ use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Gate; +use Laravel\Passport\Passport; class AuthServiceProvider extends ServiceProvider { @@ -13,7 +14,7 @@ class AuthServiceProvider extends ServiceProvider * @var array */ protected $policies = [ - // 'App\Model' => 'App\Policies\ModelPolicy', + 'App\Model' => 'App\Policies\ModelPolicy', ]; /** @@ -25,6 +26,6 @@ public function boot() { $this->registerPolicies(); - // + Passport::routes(); } } diff --git a/app/User.php b/app/User.php index e79dab7f..6cb053c7 100644 --- a/app/User.php +++ b/app/User.php @@ -6,9 +6,11 @@ use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; +use Laravel\Passport\HasApiTokens; + class User extends Authenticatable { - use Notifiable; + use HasApiTokens, Notifiable; /** * The attributes that are mass assignable. diff --git a/composer.json b/composer.json index 4c63028f..61503519 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,7 @@ "fruitcake/laravel-cors": "^1.0", "guzzlehttp/guzzle": "^6.3", "laravel/framework": "^7.0", + "laravel/passport": "^9.3", "laravel/tinker": "^2.0", "laravel/ui": "^2.0" }, diff --git a/composer.lock b/composer.lock index 40dd1ae4..d8e9c7f8 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "bd8320171484a9faab0c0543bcd46c97", + "content-hash": "a54a9c2c3f2f55ab5ad499f0dfa494dc", "packages": [ { "name": "asm89/stack-cors", @@ -110,6 +110,69 @@ ], "time": "2020-04-15T15:59:35+00:00" }, + { + "name": "defuse/php-encryption", + "version": "v2.2.1", + "source": { + "type": "git", + "url": "https://github.com/defuse/php-encryption.git", + "reference": "0f407c43b953d571421e0020ba92082ed5fb7620" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/defuse/php-encryption/zipball/0f407c43b953d571421e0020ba92082ed5fb7620", + "reference": "0f407c43b953d571421e0020ba92082ed5fb7620", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "paragonie/random_compat": ">= 2", + "php": ">=5.4.0" + }, + "require-dev": { + "nikic/php-parser": "^2.0|^3.0|^4.0", + "phpunit/phpunit": "^4|^5" + }, + "bin": [ + "bin/generate-defuse-key" + ], + "type": "library", + "autoload": { + "psr-4": { + "Defuse\\Crypto\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Hornby", + "email": "taylor@defuse.ca", + "homepage": "https://defuse.ca/" + }, + { + "name": "Scott Arciszewski", + "email": "info@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "Secure PHP Encryption Library", + "keywords": [ + "aes", + "authenticated encryption", + "cipher", + "crypto", + "cryptography", + "encrypt", + "encryption", + "openssl", + "security", + "symmetric key cryptography" + ], + "time": "2018-07-24T23:27:56+00:00" + }, { "name": "dnoegel/php-xdg-base-dir", "version": "v0.1.1", @@ -476,6 +539,56 @@ ], "time": "2020-02-22T01:51:47+00:00" }, + { + "name": "firebase/php-jwt", + "version": "v5.2.0", + "source": { + "type": "git", + "url": "https://github.com/firebase/php-jwt.git", + "reference": "feb0e820b8436873675fd3aca04f3728eb2185cb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/feb0e820b8436873675fd3aca04f3728eb2185cb", + "reference": "feb0e820b8436873675fd3aca04f3728eb2185cb", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": ">=4.8 <=9" + }, + "type": "library", + "autoload": { + "psr-4": { + "Firebase\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "keywords": [ + "jwt", + "php" + ], + "time": "2020-03-25T18:49:23+00:00" + }, { "name": "fruitcake/laravel-cors", "version": "v1.0.6", @@ -739,6 +852,158 @@ ], "time": "2019-07-01T23:21:34+00:00" }, + { + "name": "laminas/laminas-diactoros", + "version": "2.3.1", + "source": { + "type": "git", + "url": "https://github.com/laminas/laminas-diactoros.git", + "reference": "2ffc7cc816f6207b27923ee15edf6fac668390aa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/2ffc7cc816f6207b27923ee15edf6fac668390aa", + "reference": "2ffc7cc816f6207b27923ee15edf6fac668390aa", + "shasum": "" + }, + "require": { + "laminas/laminas-zendframework-bridge": "^1.0", + "php": "^7.1", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0" + }, + "conflict": { + "phpspec/prophecy": "<1.9.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" + }, + "replace": { + "zendframework/zend-diactoros": "^2.2.1" + }, + "require-dev": { + "ext-curl": "*", + "ext-dom": "*", + "ext-libxml": "*", + "http-interop/http-factory-tests": "^0.5.0", + "laminas/laminas-coding-standard": "~1.0.0", + "php-http/psr7-integration-tests": "^1.0", + "phpunit/phpunit": "^7.5.18" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.3.x-dev", + "dev-develop": "2.4.x-dev" + }, + "laminas": { + "config-provider": "Laminas\\Diactoros\\ConfigProvider", + "module": "Laminas\\Diactoros" + } + }, + "autoload": { + "files": [ + "src/functions/create_uploaded_file.php", + "src/functions/marshal_headers_from_sapi.php", + "src/functions/marshal_method_from_sapi.php", + "src/functions/marshal_protocol_version_from_sapi.php", + "src/functions/marshal_uri_from_sapi.php", + "src/functions/normalize_server.php", + "src/functions/normalize_uploaded_files.php", + "src/functions/parse_cookie_header.php", + "src/functions/create_uploaded_file.legacy.php", + "src/functions/marshal_headers_from_sapi.legacy.php", + "src/functions/marshal_method_from_sapi.legacy.php", + "src/functions/marshal_protocol_version_from_sapi.legacy.php", + "src/functions/marshal_uri_from_sapi.legacy.php", + "src/functions/normalize_server.legacy.php", + "src/functions/normalize_uploaded_files.legacy.php", + "src/functions/parse_cookie_header.legacy.php" + ], + "psr-4": { + "Laminas\\Diactoros\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "PSR HTTP Message implementations", + "homepage": "https://laminas.dev", + "keywords": [ + "http", + "laminas", + "psr", + "psr-17", + "psr-7" + ], + "funding": [ + { + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" + } + ], + "time": "2020-07-07T15:34:31+00:00" + }, + { + "name": "laminas/laminas-zendframework-bridge", + "version": "1.0.4", + "source": { + "type": "git", + "url": "https://github.com/laminas/laminas-zendframework-bridge.git", + "reference": "fcd87520e4943d968557803919523772475e8ea3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/fcd87520e4943d968557803919523772475e8ea3", + "reference": "fcd87520e4943d968557803919523772475e8ea3", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev", + "dev-develop": "1.1.x-dev" + }, + "laminas": { + "module": "Laminas\\ZendFrameworkBridge" + } + }, + "autoload": { + "files": [ + "src/autoload.php" + ], + "psr-4": { + "Laminas\\ZendFrameworkBridge\\": "src//" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Alias legacy ZF class names to Laminas Project equivalents.", + "keywords": [ + "ZendFramework", + "autoloading", + "laminas", + "zf" + ], + "funding": [ + { + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" + } + ], + "time": "2020-05-20T16:45:56+00:00" + }, { "name": "laravel/framework", "version": "v7.16.1", @@ -896,6 +1161,79 @@ ], "time": "2020-06-16T14:31:25+00:00" }, + { + "name": "laravel/passport", + "version": "v9.3.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/passport.git", + "reference": "38d9ee08974fed5d41376a52a994eaca615138a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/passport/zipball/38d9ee08974fed5d41376a52a994eaca615138a4", + "reference": "38d9ee08974fed5d41376a52a994eaca615138a4", + "shasum": "" + }, + "require": { + "ext-json": "*", + "firebase/php-jwt": "^5.0", + "guzzlehttp/guzzle": "^6.0|^7.0", + "illuminate/auth": "^6.0|^7.0", + "illuminate/console": "^6.0|^7.0", + "illuminate/container": "^6.0|^7.0", + "illuminate/contracts": "^6.0|^7.0", + "illuminate/cookie": "^6.0|^7.0", + "illuminate/database": "^6.0|^7.0", + "illuminate/encryption": "^6.0|^7.0", + "illuminate/http": "^6.0|^7.0", + "illuminate/support": "^6.0|^7.0", + "laminas/laminas-diactoros": "^2.2", + "league/oauth2-server": "^8.1", + "nyholm/psr7": "^1.0", + "php": "^7.2", + "phpseclib/phpseclib": "^2.0", + "symfony/psr-http-message-bridge": "^2.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "orchestra/testbench": "^4.4|^5.0", + "phpunit/phpunit": "^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Passport\\PassportServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Passport\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel Passport provides OAuth2 server support to Laravel.", + "keywords": [ + "laravel", + "oauth", + "passport" + ], + "time": "2020-07-21T15:16:20+00:00" + }, { "name": "laravel/tinker", "version": "v2.4.0", @@ -1015,6 +1353,71 @@ ], "time": "2020-04-29T15:06:45+00:00" }, + { + "name": "lcobucci/jwt", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/lcobucci/jwt.git", + "reference": "56f10808089e38623345e28af2f2d5e4eb579455" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/56f10808089e38623345e28af2f2d5e4eb579455", + "reference": "56f10808089e38623345e28af2f2d5e4eb579455", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "ext-openssl": "*", + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "mikey179/vfsstream": "~1.5", + "phpmd/phpmd": "~2.2", + "phpunit/php-invoker": "~1.1", + "phpunit/phpunit": "^5.7 || ^7.3", + "squizlabs/php_codesniffer": "~2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Lcobucci\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Luís Otávio Cobucci Oblonczyk", + "email": "lcobucci@gmail.com", + "role": "Developer" + } + ], + "description": "A simple library to work with JSON Web Token and JSON Web Signature", + "keywords": [ + "JWS", + "jwt" + ], + "funding": [ + { + "url": "https://github.com/lcobucci", + "type": "github" + }, + { + "url": "https://www.patreon.com/lcobucci", + "type": "patreon" + } + ], + "time": "2020-05-22T08:21:12+00:00" + }, { "name": "league/commonmark", "version": "1.5.0", @@ -1110,6 +1513,56 @@ ], "time": "2020-06-21T20:50:13+00:00" }, + { + "name": "league/event", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/event.git", + "reference": "d2cc124cf9a3fab2bb4ff963307f60361ce4d119" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/event/zipball/d2cc124cf9a3fab2bb4ff963307f60361ce4d119", + "reference": "d2cc124cf9a3fab2bb4ff963307f60361ce4d119", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "~1.0.1", + "phpspec/phpspec": "^2.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Event\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Event package", + "keywords": [ + "emitter", + "event", + "listener" + ], + "time": "2018-11-26T11:52:41+00:00" + }, { "name": "league/flysystem", "version": "1.0.69", @@ -1200,6 +1653,89 @@ ], "time": "2020-05-18T15:13:39+00:00" }, + { + "name": "league/oauth2-server", + "version": "8.1.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/oauth2-server.git", + "reference": "09f22e8121fa1832962dba18213b80d4267ef8a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/oauth2-server/zipball/09f22e8121fa1832962dba18213b80d4267ef8a3", + "reference": "09f22e8121fa1832962dba18213b80d4267ef8a3", + "shasum": "" + }, + "require": { + "defuse/php-encryption": "^2.2.1", + "ext-json": "*", + "ext-openssl": "*", + "lcobucci/jwt": "^3.3.1", + "league/event": "^2.2", + "php": ">=7.2.0", + "psr/http-message": "^1.0.1" + }, + "replace": { + "league/oauth2server": "*", + "lncd/oauth2": "*" + }, + "require-dev": { + "laminas/laminas-diactoros": "^2.3.0", + "phpstan/phpstan": "^0.11.19", + "phpstan/phpstan-phpunit": "^0.11.2", + "phpunit/phpunit": "^8.5.4 || ^9.1.3", + "roave/security-advisories": "dev-master" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\OAuth2\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alex Bilbie", + "email": "hello@alexbilbie.com", + "homepage": "http://www.alexbilbie.com", + "role": "Developer" + }, + { + "name": "Andy Millington", + "email": "andrew@noexceptions.io", + "homepage": "https://www.noexceptions.io", + "role": "Developer" + } + ], + "description": "A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.", + "homepage": "https://oauth2.thephpleague.com/", + "keywords": [ + "Authentication", + "api", + "auth", + "authorisation", + "authorization", + "oauth", + "oauth 2", + "oauth 2.0", + "oauth2", + "protect", + "resource", + "secure", + "server" + ], + "funding": [ + { + "url": "https://github.com/sephster", + "type": "github" + } + ], + "time": "2020-07-01T11:33:50+00:00" + }, { "name": "monolog/monolog", "version": "2.1.0", @@ -1384,47 +1920,120 @@ }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/53c2753d756f5adb586dca79c2ec0e2654dd9463", - "reference": "53c2753d756f5adb586dca79c2ec0e2654dd9463", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/53c2753d756f5adb586dca79c2ec0e2654dd9463", + "reference": "53c2753d756f5adb586dca79c2ec0e2654dd9463", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "ircmaxell/php-yacc": "0.0.5", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "time": "2020-06-03T07:24:19+00:00" + }, + { + "name": "nyholm/psr7", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/Nyholm/psr7.git", + "reference": "c17f4f73985f62054a331cbc4ffdf9868c4ef256" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Nyholm/psr7/zipball/c17f4f73985f62054a331cbc4ffdf9868c4ef256", + "reference": "c17f4f73985f62054a331cbc4ffdf9868c4ef256", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": ">=7.0" + "php": "^7.1", + "php-http/message-factory": "^1.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0" + }, + "provide": { + "psr/http-factory-implementation": "1.0", + "psr/http-message-implementation": "1.0" }, "require-dev": { - "ircmaxell/php-yacc": "0.0.5", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0" + "http-interop/http-factory-tests": "dev-master", + "php-http/psr7-integration-tests": "^1.0", + "phpunit/phpunit": "^7.5", + "symfony/error-handler": "^4.4" }, - "bin": [ - "bin/php-parse" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "4.3-dev" + "dev-master": "1.0-dev" } }, "autoload": { "psr-4": { - "PhpParser\\": "lib/PhpParser" + "Nyholm\\Psr7\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Nikita Popov" + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + }, + { + "name": "Martijn van der Ven", + "email": "martijn@vanderven.se" } ], - "description": "A PHP parser written in PHP", + "description": "A fast PHP7 implementation of PSR-7", + "homepage": "http://tnyholm.se", "keywords": [ - "parser", - "php" + "psr-17", + "psr-7" ], - "time": "2020-06-03T07:24:19+00:00" + "funding": [ + { + "url": "https://github.com/Zegnat", + "type": "github" + }, + { + "url": "https://github.com/nyholm", + "type": "github" + } + ], + "time": "2020-05-23T11:29:07+00:00" }, { "name": "opis/closure", @@ -1487,6 +2096,101 @@ ], "time": "2020-06-17T14:59:55+00:00" }, + { + "name": "paragonie/random_compat", + "version": "v9.99.99", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "reference": "84b4dfb120c6f9b4ff7b3685f9b8f1aa365a0c95", + "shasum": "" + }, + "require": { + "php": "^7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "time": "2018-07-02T15:55:56+00:00" + }, + { + "name": "php-http/message-factory", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-http/message-factory.git", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/message-factory/zipball/a478cb11f66a6ac48d8954216cfed9aa06a501a1", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Factory interfaces for PSR-7 HTTP Message", + "homepage": "http://php-http.org", + "keywords": [ + "factory", + "http", + "message", + "stream", + "uri" + ], + "time": "2015-12-19T14:08:53+00:00" + }, { "name": "phpoption/phpoption", "version": "1.7.4", @@ -1552,6 +2256,112 @@ ], "time": "2020-06-07T10:40:07+00:00" }, + { + "name": "phpseclib/phpseclib", + "version": "2.0.28", + "source": { + "type": "git", + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "d1ca58cf33cb21046d702ae3a7b14fdacd9f3260" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d1ca58cf33cb21046d702ae3a7b14fdacd9f3260", + "reference": "d1ca58cf33cb21046d702ae3a7b14fdacd9f3260", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phing/phing": "~2.7", + "phpunit/phpunit": "^4.8.35|^5.7|^6.0", + "sami/sami": "~2.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "suggest": { + "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." + }, + "type": "library", + "autoload": { + "files": [ + "phpseclib/bootstrap.php" + ], + "psr-4": { + "phpseclib\\": "phpseclib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jim Wigginton", + "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", + "role": "Developer" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "role": "Developer" + } + ], + "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", + "homepage": "http://phpseclib.sourceforge.net", + "keywords": [ + "BigInteger", + "aes", + "asn.1", + "asn1", + "blowfish", + "crypto", + "cryptography", + "encryption", + "rsa", + "security", + "sftp", + "signature", + "signing", + "ssh", + "twofish", + "x.509", + "x509" + ], + "funding": [ + { + "url": "https://github.com/terrafrost", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpseclib", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", + "type": "tidelift" + } + ], + "time": "2020-07-08T09:08:33+00:00" + }, { "name": "psr/container", "version": "1.0.0", @@ -1647,6 +2457,58 @@ ], "time": "2019-01-08T18:20:26+00:00" }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "time": "2019-04-30T12:38:16+00:00" + }, { "name": "psr/http-message", "version": "1.0.1", @@ -3617,6 +4479,84 @@ ], "time": "2020-05-30T20:35:19+00:00" }, + { + "name": "symfony/psr-http-message-bridge", + "version": "v2.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/psr-http-message-bridge.git", + "reference": "e44f249afab496b4e8c0f7461fb8140eaa4b24d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/e44f249afab496b4e8c0f7461fb8140eaa4b24d2", + "reference": "e44f249afab496b4e8c0f7461fb8140eaa4b24d2", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0", + "symfony/http-foundation": "^4.4 || ^5.0" + }, + "require-dev": { + "nyholm/psr7": "^1.1", + "symfony/phpunit-bridge": "^4.4 || ^5.0" + }, + "suggest": { + "nyholm/psr7": "For a super lightweight PSR-7/17 implementation" + }, + "type": "symfony-bridge", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bridge\\PsrHttpMessage\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + } + ], + "description": "PSR HTTP message bridge", + "homepage": "http://symfony.com", + "keywords": [ + "http", + "http-message", + "psr-17", + "psr-7" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-06-25T08:21:47+00:00" + }, { "name": "symfony/routing", "version": "v5.1.2", diff --git a/config/auth.php b/config/auth.php index aaf982bc..04c6eec2 100644 --- a/config/auth.php +++ b/config/auth.php @@ -42,7 +42,7 @@ ], 'api' => [ - 'driver' => 'token', + 'driver' => 'passport', 'provider' => 'users', 'hash' => false, ], diff --git a/package.json b/package.json index 3f41e26e..d693fb98 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "devDependencies": { "axios": "^0.19", "bootstrap": "^4.0.0", - "cross-env": "^7.0", + "cross-env": "^7.0.2", "jquery": "^3.2", "laravel-mix": "^5.0.1", "lodash": "^4.17.19", diff --git a/public/js/app.js b/public/js/app.js index 6689a794..40254dbc 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -1932,6 +1932,841 @@ __webpack_require__.r(__webpack_exports__); /***/ }), +/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/AuthorizedClients.vue?vue&type=script&lang=js&": +/*!*************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/passport/AuthorizedClients.vue?vue&type=script&lang=js& ***! + \*************************************************************************************************************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +/* harmony default export */ __webpack_exports__["default"] = ({ + /* + * The component's data. + */ + data: function data() { + return { + tokens: [] + }; + }, + + /** + * Prepare the component (Vue 1.x). + */ + ready: function ready() { + this.prepareComponent(); + }, + + /** + * Prepare the component (Vue 2.x). + */ + mounted: function mounted() { + this.prepareComponent(); + }, + methods: { + /** + * Prepare the component (Vue 2.x). + */ + prepareComponent: function prepareComponent() { + this.getTokens(); + }, + + /** + * Get all of the authorized tokens for the user. + */ + getTokens: function getTokens() { + var _this = this; + + axios.get('/oauth/tokens').then(function (response) { + _this.tokens = response.data; + }); + }, + + /** + * Revoke the given token. + */ + revoke: function revoke(token) { + var _this2 = this; + + axios["delete"]('/oauth/tokens/' + token.id).then(function (response) { + _this2.getTokens(); + }); + } + } +}); + +/***/ }), + +/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/Clients.vue?vue&type=script&lang=js&": +/*!***************************************************************************************************************************************************************************!*\ + !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/passport/Clients.vue?vue&type=script&lang=js& ***! + \***************************************************************************************************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +/* harmony default export */ __webpack_exports__["default"] = ({ + /* + * The component's data. + */ + data: function data() { + return { + clients: [], + clientSecret: null, + createForm: { + errors: [], + name: '', + redirect: '', + confidential: true + }, + editForm: { + errors: [], + name: '', + redirect: '' + } + }; + }, + + /** + * Prepare the component (Vue 1.x). + */ + ready: function ready() { + this.prepareComponent(); + }, + + /** + * Prepare the component (Vue 2.x). + */ + mounted: function mounted() { + this.prepareComponent(); + }, + methods: { + /** + * Prepare the component. + */ + prepareComponent: function prepareComponent() { + this.getClients(); + $('#modal-create-client').on('shown.bs.modal', function () { + $('#create-client-name').focus(); + }); + $('#modal-edit-client').on('shown.bs.modal', function () { + $('#edit-client-name').focus(); + }); + }, + + /** + * Get all of the OAuth clients for the user. + */ + getClients: function getClients() { + var _this = this; + + axios.get('/oauth/clients').then(function (response) { + _this.clients = response.data; + }); + }, + + /** + * Show the form for creating new clients. + */ + showCreateClientForm: function showCreateClientForm() { + $('#modal-create-client').modal('show'); + }, + + /** + * Create a new OAuth client for the user. + */ + store: function store() { + this.persistClient('post', '/oauth/clients', this.createForm, '#modal-create-client'); + }, + + /** + * Edit the given client. + */ + edit: function edit(client) { + this.editForm.id = client.id; + this.editForm.name = client.name; + this.editForm.redirect = client.redirect; + $('#modal-edit-client').modal('show'); + }, + + /** + * Update the client being edited. + */ + update: function update() { + this.persistClient('put', '/oauth/clients/' + this.editForm.id, this.editForm, '#modal-edit-client'); + }, + + /** + * Persist the client to storage using the given form. + */ + persistClient: function persistClient(method, uri, form, modal) { + var _this2 = this; + + form.errors = []; + axios[method](uri, form).then(function (response) { + _this2.getClients(); + + form.name = ''; + form.redirect = ''; + form.errors = []; + $(modal).modal('hide'); + + if (response.data.plainSecret) { + _this2.showClientSecret(response.data.plainSecret); + } + })["catch"](function (error) { + if (_typeof(error.response.data) === 'object') { + form.errors = _.flatten(_.toArray(error.response.data.errors)); + } else { + form.errors = ['Something went wrong. Please try again.']; + } + }); + }, + + /** + * Show the given client secret to the user. + */ + showClientSecret: function showClientSecret(clientSecret) { + this.clientSecret = clientSecret; + $('#modal-client-secret').modal('show'); + }, + + /** + * Destroy the given client. + */ + destroy: function destroy(client) { + var _this3 = this; + + axios["delete"]('/oauth/clients/' + client.id).then(function (response) { + _this3.getClients(); + }); + } + } +}); + +/***/ }), + +/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=script&lang=js&": +/*!****************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=script&lang=js& ***! + \****************************************************************************************************************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +/* harmony default export */ __webpack_exports__["default"] = ({ + /* + * The component's data. + */ + data: function data() { + return { + accessToken: null, + tokens: [], + scopes: [], + form: { + name: '', + scopes: [], + errors: [] + } + }; + }, + + /** + * Prepare the component (Vue 1.x). + */ + ready: function ready() { + this.prepareComponent(); + }, + + /** + * Prepare the component (Vue 2.x). + */ + mounted: function mounted() { + this.prepareComponent(); + }, + methods: { + /** + * Prepare the component. + */ + prepareComponent: function prepareComponent() { + this.getTokens(); + this.getScopes(); + $('#modal-create-token').on('shown.bs.modal', function () { + $('#create-token-name').focus(); + }); + }, + + /** + * Get all of the personal access tokens for the user. + */ + getTokens: function getTokens() { + var _this = this; + + axios.get('/oauth/personal-access-tokens').then(function (response) { + _this.tokens = response.data; + }); + }, + + /** + * Get all of the available scopes. + */ + getScopes: function getScopes() { + var _this2 = this; + + axios.get('/oauth/scopes').then(function (response) { + _this2.scopes = response.data; + }); + }, + + /** + * Show the form for creating new tokens. + */ + showCreateTokenForm: function showCreateTokenForm() { + $('#modal-create-token').modal('show'); + }, + + /** + * Create a new personal access token. + */ + store: function store() { + var _this3 = this; + + this.accessToken = null; + this.form.errors = []; + axios.post('/oauth/personal-access-tokens', this.form).then(function (response) { + _this3.form.name = ''; + _this3.form.scopes = []; + _this3.form.errors = []; + + _this3.tokens.push(response.data.token); + + _this3.showAccessToken(response.data.accessToken); + })["catch"](function (error) { + if (_typeof(error.response.data) === 'object') { + _this3.form.errors = _.flatten(_.toArray(error.response.data.errors)); + } else { + _this3.form.errors = ['Something went wrong. Please try again.']; + } + }); + }, + + /** + * Toggle the given scope in the list of assigned scopes. + */ + toggleScope: function toggleScope(scope) { + if (this.scopeIsAssigned(scope)) { + this.form.scopes = _.reject(this.form.scopes, function (s) { + return s == scope; + }); + } else { + this.form.scopes.push(scope); + } + }, + + /** + * Determine if the given scope has been assigned to the token. + */ + scopeIsAssigned: function scopeIsAssigned(scope) { + return _.indexOf(this.form.scopes, scope) >= 0; + }, + + /** + * Show the given access token to the user. + */ + showAccessToken: function showAccessToken(accessToken) { + $('#modal-create-token').modal('hide'); + this.accessToken = accessToken; + $('#modal-access-token').modal('show'); + }, + + /** + * Revoke the given token. + */ + revoke: function revoke(token) { + var _this4 = this; + + axios["delete"]('/oauth/personal-access-tokens/' + token.id).then(function (response) { + _this4.getTokens(); + }); + } + } +}); + +/***/ }), + /***/ "./node_modules/bootstrap/dist/js/bootstrap.js": /*!*****************************************************!*\ !*** ./node_modules/bootstrap/dist/js/bootstrap.js ***! @@ -6360,6 +7195,150 @@ __webpack_require__.r(__webpack_exports__); //# sourceMappingURL=bootstrap.js.map +/***/ }), + +/***/ "./node_modules/css-loader/index.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/AuthorizedClients.vue?vue&type=style&index=0&id=397d14ca&scoped=true&lang=css&": +/*!********************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/css-loader??ref--6-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--6-2!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/passport/AuthorizedClients.vue?vue&type=style&index=0&id=397d14ca&scoped=true&lang=css& ***! + \********************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +exports = module.exports = __webpack_require__(/*! ../../../../node_modules/css-loader/lib/css-base.js */ "./node_modules/css-loader/lib/css-base.js")(false); +// imports + + +// module +exports.push([module.i, "\n.action-link[data-v-397d14ca] {\n cursor: pointer;\n}\n", ""]); + +// exports + + +/***/ }), + +/***/ "./node_modules/css-loader/index.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/Clients.vue?vue&type=style&index=0&id=1552a5b6&scoped=true&lang=css&": +/*!**********************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/css-loader??ref--6-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--6-2!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/passport/Clients.vue?vue&type=style&index=0&id=1552a5b6&scoped=true&lang=css& ***! + \**********************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +exports = module.exports = __webpack_require__(/*! ../../../../node_modules/css-loader/lib/css-base.js */ "./node_modules/css-loader/lib/css-base.js")(false); +// imports + + +// module +exports.push([module.i, "\n.action-link[data-v-1552a5b6] {\n cursor: pointer;\n}\n", ""]); + +// exports + + +/***/ }), + +/***/ "./node_modules/css-loader/index.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=style&index=0&id=49962cc0&scoped=true&lang=css&": +/*!***********************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/css-loader??ref--6-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--6-2!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=style&index=0&id=49962cc0&scoped=true&lang=css& ***! + \***********************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +exports = module.exports = __webpack_require__(/*! ../../../../node_modules/css-loader/lib/css-base.js */ "./node_modules/css-loader/lib/css-base.js")(false); +// imports + + +// module +exports.push([module.i, "\n.action-link[data-v-49962cc0] {\n cursor: pointer;\n}\n", ""]); + +// exports + + +/***/ }), + +/***/ "./node_modules/css-loader/lib/css-base.js": +/*!*************************************************!*\ + !*** ./node_modules/css-loader/lib/css-base.js ***! + \*************************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +// css base code, injected by the css-loader +module.exports = function(useSourceMap) { + var list = []; + + // return the list of modules as css string + list.toString = function toString() { + return this.map(function (item) { + var content = cssWithMappingToString(item, useSourceMap); + if(item[2]) { + return "@media " + item[2] + "{" + content + "}"; + } else { + return content; + } + }).join(""); + }; + + // import a list of modules into the list + list.i = function(modules, mediaQuery) { + if(typeof modules === "string") + modules = [[null, modules, ""]]; + var alreadyImportedModules = {}; + for(var i = 0; i < this.length; i++) { + var id = this[i][0]; + if(typeof id === "number") + alreadyImportedModules[id] = true; + } + for(i = 0; i < modules.length; i++) { + var item = modules[i]; + // skip already imported module + // this implementation is not 100% perfect for weird media query combinations + // when a module is imported multiple times with different media queries. + // I hope this will never occur (Hey this way we have smaller bundles) + if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) { + if(mediaQuery && !item[2]) { + item[2] = mediaQuery; + } else if(mediaQuery) { + item[2] = "(" + item[2] + ") and (" + mediaQuery + ")"; + } + list.push(item); + } + } + }; + return list; +}; + +function cssWithMappingToString(item, useSourceMap) { + var content = item[1] || ''; + var cssMapping = item[3]; + if (!cssMapping) { + return content; + } + + if (useSourceMap && typeof btoa === 'function') { + var sourceMapping = toComment(cssMapping); + var sourceURLs = cssMapping.sources.map(function (source) { + return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */' + }); + + return [content].concat(sourceURLs).concat([sourceMapping]).join('\n'); + } + + return [content].join('\n'); +} + +// Adapted from convert-source-map (MIT) +function toComment(sourceMap) { + // eslint-disable-next-line no-undef + var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))); + var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64; + + return '/*# ' + data + ' */'; +} + + /***/ }), /***/ "./node_modules/jquery/dist/jquery.js": @@ -17267,7 +18246,7 @@ return jQuery; var undefined; /** Used as the semantic version number. */ - var VERSION = '4.17.15'; + var VERSION = '4.17.19'; /** Used as the size to enable large array optimizations. */ var LARGE_ARRAY_SIZE = 200; @@ -20974,8 +21953,21 @@ return jQuery; * @returns {Array} Returns the new sorted array. */ function baseOrderBy(collection, iteratees, orders) { + if (iteratees.length) { + iteratees = arrayMap(iteratees, function(iteratee) { + if (isArray(iteratee)) { + return function(value) { + return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee); + } + } + return iteratee; + }); + } else { + iteratees = [identity]; + } + var index = -1; - iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee())); + iteratees = arrayMap(iteratees, baseUnary(getIteratee())); var result = baseMap(collection, function(value, key, collection) { var criteria = arrayMap(iteratees, function(iteratee) { @@ -21232,6 +22224,10 @@ return jQuery; var key = toKey(path[index]), newValue = value; + if (key === '__proto__' || key === 'constructor' || key === 'prototype') { + return object; + } + if (index != lastIndex) { var objValue = nested[key]; newValue = customizer ? customizer(objValue, key, nested) : undefined; @@ -21384,11 +22380,14 @@ return jQuery; * into `array`. */ function baseSortedIndexBy(array, value, iteratee, retHighest) { - value = iteratee(value); - var low = 0, - high = array == null ? 0 : array.length, - valIsNaN = value !== value, + high = array == null ? 0 : array.length; + if (high === 0) { + return 0; + } + + value = iteratee(value); + var valIsNaN = value !== value, valIsNull = value === null, valIsSymbol = isSymbol(value), valIsUndefined = value === undefined; @@ -22873,10 +23872,11 @@ return jQuery; if (arrLength != othLength && !(isPartial && othLength > arrLength)) { return false; } - // Assume cyclic values are equal. - var stacked = stack.get(array); - if (stacked && stack.get(other)) { - return stacked == other; + // Check that cyclic values are equal. + var arrStacked = stack.get(array); + var othStacked = stack.get(other); + if (arrStacked && othStacked) { + return arrStacked == other && othStacked == array; } var index = -1, result = true, @@ -23038,10 +24038,11 @@ return jQuery; return false; } } - // Assume cyclic values are equal. - var stacked = stack.get(object); - if (stacked && stack.get(other)) { - return stacked == other; + // Check that cyclic values are equal. + var objStacked = stack.get(object); + var othStacked = stack.get(other); + if (objStacked && othStacked) { + return objStacked == other && othStacked == object; } var result = true; stack.set(object, other); @@ -26422,6 +27423,10 @@ return jQuery; * // The `_.property` iteratee shorthand. * _.filter(users, 'active'); * // => objects for ['barney'] + * + * // Combining several predicates using `_.overEvery` or `_.overSome`. + * _.filter(users, _.overSome([{ 'age': 36 }, ['age', 40]])); + * // => objects for ['fred', 'barney'] */ function filter(collection, predicate) { var func = isArray(collection) ? arrayFilter : baseFilter; @@ -27171,15 +28176,15 @@ return jQuery; * var users = [ * { 'user': 'fred', 'age': 48 }, * { 'user': 'barney', 'age': 36 }, - * { 'user': 'fred', 'age': 40 }, + * { 'user': 'fred', 'age': 30 }, * { 'user': 'barney', 'age': 34 } * ]; * * _.sortBy(users, [function(o) { return o.user; }]); - * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] + * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]] * * _.sortBy(users, ['user', 'age']); - * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]] + * // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]] */ var sortBy = baseRest(function(collection, iteratees) { if (collection == null) { @@ -32054,11 +33059,11 @@ return jQuery; // Use a sourceURL for easier debugging. // The sourceURL gets injected into the source that's eval-ed, so be careful - // with lookup (in case of e.g. prototype pollution), and strip newlines if any. - // A newline wouldn't be a valid sourceURL anyway, and it'd enable code injection. + // to normalize all kinds of whitespace, so e.g. newlines (and unicode versions of it) can't sneak in + // and escape the comment, thus injecting code that gets evaled. var sourceURL = '//# sourceURL=' + (hasOwnProperty.call(options, 'sourceURL') - ? (options.sourceURL + '').replace(/[\r\n]/g, ' ') + ? (options.sourceURL + '').replace(/\s/g, ' ') : ('lodash.templateSources[' + (++templateCounter) + ']') ) + '\n'; @@ -32091,8 +33096,6 @@ return jQuery; // If `variable` is not specified wrap a with-statement around the generated // code to add the data object to the top of the scope chain. - // Like with sourceURL, we take care to not check the option's prototype, - // as this configuration is a code injection vector. var variable = hasOwnProperty.call(options, 'variable') && options.variable; if (!variable) { source = 'with (obj) {\n' + source + '\n}\n'; @@ -32799,6 +33802,9 @@ return jQuery; * values against any array or object value, respectively. See `_.isEqual` * for a list of supported value comparisons. * + * **Note:** Multiple values can be checked by combining several matchers + * using `_.overSome` + * * @static * @memberOf _ * @since 3.0.0 @@ -32814,6 +33820,10 @@ return jQuery; * * _.filter(objects, _.matches({ 'a': 4, 'c': 6 })); * // => [{ 'a': 4, 'b': 5, 'c': 6 }] + * + * // Checking for several possible values + * _.filter(users, _.overSome([_.matches({ 'a': 1 }), _.matches({ 'a': 4 })])); + * // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }] */ function matches(source) { return baseMatches(baseClone(source, CLONE_DEEP_FLAG)); @@ -32828,6 +33838,9 @@ return jQuery; * `srcValue` values against any array or object value, respectively. See * `_.isEqual` for a list of supported value comparisons. * + * **Note:** Multiple values can be checked by combining several matchers + * using `_.overSome` + * * @static * @memberOf _ * @since 3.2.0 @@ -32844,6 +33857,10 @@ return jQuery; * * _.find(objects, _.matchesProperty('a', 4)); * // => { 'a': 4, 'b': 5, 'c': 6 } + * + * // Checking for several possible values + * _.filter(users, _.overSome([_.matchesProperty('a', 1), _.matchesProperty('a', 4)])); + * // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }] */ function matchesProperty(path, srcValue) { return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG)); @@ -33067,6 +34084,10 @@ return jQuery; * Creates a function that checks if **all** of the `predicates` return * truthy when invoked with the arguments it receives. * + * Following shorthands are possible for providing predicates. + * Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate. + * Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them. + * * @static * @memberOf _ * @since 4.0.0 @@ -33093,6 +34114,10 @@ return jQuery; * Creates a function that checks if **any** of the `predicates` return * truthy when invoked with the arguments it receives. * + * Following shorthands are possible for providing predicates. + * Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate. + * Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them. + * * @static * @memberOf _ * @since 4.0.0 @@ -33112,6 +34137,9 @@ return jQuery; * * func(NaN); * // => false + * + * var matchesFunc = _.overSome([{ 'a': 1 }, { 'a': 2 }]) + * var matchesPropertyFunc = _.overSome([['a', 1], ['a', 2]]) */ var overSome = createOver(arraySome); @@ -37383,6 +38411,605 @@ process.umask = function() { return 0; }; /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../webpack/buildin/global.js */ "./node_modules/webpack/buildin/global.js"), __webpack_require__(/*! ./../process/browser.js */ "./node_modules/process/browser.js"))) +/***/ }), + +/***/ "./node_modules/style-loader/index.js!./node_modules/css-loader/index.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/AuthorizedClients.vue?vue&type=style&index=0&id=397d14ca&scoped=true&lang=css&": +/*!************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/style-loader!./node_modules/css-loader??ref--6-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--6-2!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/passport/AuthorizedClients.vue?vue&type=style&index=0&id=397d14ca&scoped=true&lang=css& ***! + \************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + + +var content = __webpack_require__(/*! !../../../../node_modules/css-loader??ref--6-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/postcss-loader/src??ref--6-2!../../../../node_modules/vue-loader/lib??vue-loader-options!./AuthorizedClients.vue?vue&type=style&index=0&id=397d14ca&scoped=true&lang=css& */ "./node_modules/css-loader/index.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/AuthorizedClients.vue?vue&type=style&index=0&id=397d14ca&scoped=true&lang=css&"); + +if(typeof content === 'string') content = [[module.i, content, '']]; + +var transform; +var insertInto; + + + +var options = {"hmr":true} + +options.transform = transform +options.insertInto = undefined; + +var update = __webpack_require__(/*! ../../../../node_modules/style-loader/lib/addStyles.js */ "./node_modules/style-loader/lib/addStyles.js")(content, options); + +if(content.locals) module.exports = content.locals; + +if(false) {} + +/***/ }), + +/***/ "./node_modules/style-loader/index.js!./node_modules/css-loader/index.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/Clients.vue?vue&type=style&index=0&id=1552a5b6&scoped=true&lang=css&": +/*!**************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/style-loader!./node_modules/css-loader??ref--6-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--6-2!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/passport/Clients.vue?vue&type=style&index=0&id=1552a5b6&scoped=true&lang=css& ***! + \**************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + + +var content = __webpack_require__(/*! !../../../../node_modules/css-loader??ref--6-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/postcss-loader/src??ref--6-2!../../../../node_modules/vue-loader/lib??vue-loader-options!./Clients.vue?vue&type=style&index=0&id=1552a5b6&scoped=true&lang=css& */ "./node_modules/css-loader/index.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/Clients.vue?vue&type=style&index=0&id=1552a5b6&scoped=true&lang=css&"); + +if(typeof content === 'string') content = [[module.i, content, '']]; + +var transform; +var insertInto; + + + +var options = {"hmr":true} + +options.transform = transform +options.insertInto = undefined; + +var update = __webpack_require__(/*! ../../../../node_modules/style-loader/lib/addStyles.js */ "./node_modules/style-loader/lib/addStyles.js")(content, options); + +if(content.locals) module.exports = content.locals; + +if(false) {} + +/***/ }), + +/***/ "./node_modules/style-loader/index.js!./node_modules/css-loader/index.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=style&index=0&id=49962cc0&scoped=true&lang=css&": +/*!***************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/style-loader!./node_modules/css-loader??ref--6-1!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src??ref--6-2!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=style&index=0&id=49962cc0&scoped=true&lang=css& ***! + \***************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + + +var content = __webpack_require__(/*! !../../../../node_modules/css-loader??ref--6-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/postcss-loader/src??ref--6-2!../../../../node_modules/vue-loader/lib??vue-loader-options!./PersonalAccessTokens.vue?vue&type=style&index=0&id=49962cc0&scoped=true&lang=css& */ "./node_modules/css-loader/index.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=style&index=0&id=49962cc0&scoped=true&lang=css&"); + +if(typeof content === 'string') content = [[module.i, content, '']]; + +var transform; +var insertInto; + + + +var options = {"hmr":true} + +options.transform = transform +options.insertInto = undefined; + +var update = __webpack_require__(/*! ../../../../node_modules/style-loader/lib/addStyles.js */ "./node_modules/style-loader/lib/addStyles.js")(content, options); + +if(content.locals) module.exports = content.locals; + +if(false) {} + +/***/ }), + +/***/ "./node_modules/style-loader/lib/addStyles.js": +/*!****************************************************!*\ + !*** ./node_modules/style-loader/lib/addStyles.js ***! + \****************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ + +var stylesInDom = {}; + +var memoize = function (fn) { + var memo; + + return function () { + if (typeof memo === "undefined") memo = fn.apply(this, arguments); + return memo; + }; +}; + +var isOldIE = memoize(function () { + // Test for IE <= 9 as proposed by Browserhacks + // @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805 + // Tests for existence of standard globals is to allow style-loader + // to operate correctly into non-standard environments + // @see https://github.com/webpack-contrib/style-loader/issues/177 + return window && document && document.all && !window.atob; +}); + +var getTarget = function (target, parent) { + if (parent){ + return parent.querySelector(target); + } + return document.querySelector(target); +}; + +var getElement = (function (fn) { + var memo = {}; + + return function(target, parent) { + // If passing function in options, then use it for resolve "head" element. + // Useful for Shadow Root style i.e + // { + // insertInto: function () { return document.querySelector("#foo").shadowRoot } + // } + if (typeof target === 'function') { + return target(); + } + if (typeof memo[target] === "undefined") { + var styleTarget = getTarget.call(this, target, parent); + // Special case to return head of iframe instead of iframe itself + if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) { + try { + // This will throw an exception if access to iframe is blocked + // due to cross-origin restrictions + styleTarget = styleTarget.contentDocument.head; + } catch(e) { + styleTarget = null; + } + } + memo[target] = styleTarget; + } + return memo[target] + }; +})(); + +var singleton = null; +var singletonCounter = 0; +var stylesInsertedAtTop = []; + +var fixUrls = __webpack_require__(/*! ./urls */ "./node_modules/style-loader/lib/urls.js"); + +module.exports = function(list, options) { + if (typeof DEBUG !== "undefined" && DEBUG) { + if (typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment"); + } + + options = options || {}; + + options.attrs = typeof options.attrs === "object" ? options.attrs : {}; + + // Force single-tag solution on IE6-9, which has a hard limit on the # of + + + + diff --git a/resources/js/components/passport/Clients.vue b/resources/js/components/passport/Clients.vue new file mode 100644 index 00000000..522233f5 --- /dev/null +++ b/resources/js/components/passport/Clients.vue @@ -0,0 +1,416 @@ + + + + + diff --git a/resources/js/components/passport/PersonalAccessTokens.vue b/resources/js/components/passport/PersonalAccessTokens.vue new file mode 100644 index 00000000..7eedfe97 --- /dev/null +++ b/resources/js/components/passport/PersonalAccessTokens.vue @@ -0,0 +1,298 @@ + + + + + diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index 05dfca92..6d51caae 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -7,15 +7,9 @@
Dashboard
-
- @if (session('status')) - - @endif - - You are logged in! -
+ + +
From 1ceda459e9c7e1c5fa311a1b27658b23ec283f23 Mon Sep 17 00:00:00 2001 From: Simon Date: Tue, 22 Sep 2020 02:20:50 +0200 Subject: [PATCH 02/80] Account authentication refactor Account type list Helper Account type name & hiscore url format Helper AccountAuthController & Model --- app/AccountAuthStatus.php | 4 +- app/Helpers/Helper.php | 12 ++ .../Controllers/AccountAuthController.php | 111 +++++++++++++ app/Http/Controllers/AccountController.php | 56 +------ .../Controllers/Api/AccountController.php | 150 +++++++++--------- app/User.php | 4 + ...020_08_14_225333_create_accounts_table.php | 4 +- ...912_create_account_auth_statuses_table.php | 3 + .../images/{group.png => group_ironman.png} | Bin .../{hardcore.png => hardcore_ironman.png} | Bin .../{ultimate.png => ultimate_ironman.png} | Bin resources/views/account/auth.blade.php | 52 +++++- resources/views/account/create.blade.php | 64 +++----- routes/api.php | 2 +- routes/web.php | 6 +- 15 files changed, 290 insertions(+), 178 deletions(-) create mode 100644 app/Http/Controllers/AccountAuthController.php rename public/images/{group.png => group_ironman.png} (100%) rename public/images/{hardcore.png => hardcore_ironman.png} (100%) rename public/images/{ultimate.png => ultimate_ironman.png} (100%) diff --git a/app/AccountAuthStatus.php b/app/AccountAuthStatus.php index 8d06900e..bbd4fe45 100644 --- a/app/AccountAuthStatus.php +++ b/app/AccountAuthStatus.php @@ -6,5 +6,7 @@ class AccountAuthStatus extends Model { - // + public function user() { + return $this->belongsTo(User::class); + } } diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php index 6f0cf55c..bcbbe517 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -173,4 +173,16 @@ public static function accountStats($accountId) { return $accountSkills; } + + public static function listAccountTypes() { + return ["normal", "ironman", "hardcore_ironman", "ultimate_ironman"]; + } + + public static function formatAccountTypeName($accountType) { + return ucfirst(str_replace('_', ' ', $accountType)); + } + + public static function formatHiscoreUrl($accountType, $playerName) { + return 'https://secure.runescape.com/m=hiscore_oldschool'.($accountType === 'normal' ? '' : '_'.($accountType === 'ultimate_ironman' ? 'ultimate' : $accountType)).'/index_lite.ws?player='.str_replace(' ', '%20', $playerName); + } } diff --git a/app/Http/Controllers/AccountAuthController.php b/app/Http/Controllers/AccountAuthController.php new file mode 100644 index 00000000..051466ae --- /dev/null +++ b/app/Http/Controllers/AccountAuthController.php @@ -0,0 +1,111 @@ +id)->where('status', '!=', 'success')->first(); + + if ($authStatus) { + return view('account.auth', compact('authStatus')); + } else { + return redirect(route('create-account'))->withErrors(['You should register a Old School RuneScape account first!']); + } + } else { + return redirect(route('login'))->withErrors(['You have to log in before linking a Old School RuneScape account!']); + } + } + + /** + * Verifies incoming account registration request. + * + * @return + */ + public function create() { + if (Auth::check()) { + request()->validate([ + 'username' => ['required', 'string', 'min:1', 'max:13'], + 'account_type' => ['required', Rule::in(Helper::listAccountTypes())], + ]); + + if (Account::where('username', request('username'))->count() == 0) { + $authStatus = AccountAuthStatus::where('username', request('username'))->first(); + + if ($authStatus) { + if (Auth::user()->id === $authStatus->user_id) { + return view('account.auth', compact('authStatus')); + } + + return redirect()->back()->withErrors('This account has already been linked to another profile with status: '.$authStatus->status.'!'); + } else { + $playerDataUrl = Helper::formatHiscoreUrl(request('account_type'), request('username')); + + if (Helper::verifyUrl($playerDataUrl)) { + $authStatus = new AccountAuthStatus; + + $authStatus->user_id = Auth::user()->id; + $authStatus->account_type = request('account_type'); + $authStatus->username = request('username'); + $authStatus->code = substr(md5(uniqid(mt_rand(), true)), 0, 8); + $authStatus->status = "pending"; + + $authStatus->save(); + + return view('account.auth', compact('authStatus')); + } else { + return redirect()->back()->withErrors('Could not find this Old School RuneScape account! Did you pick correct account type?'); + } + } + } else { + return redirect()->back()->withErrors('This account is already registered and authenticated!'); + } + } else { + return redirect(route('login'))->withErrors(['You have to log in before linking a Old School RuneScape account!']); + } + } + + public function updateAccountType() { + $authStatus = AccountAuthStatus::where('user_id', Auth::user()->id)->where('status', '!=', 'success')->first(); + + if ($authStatus) { + if ($authStatus->account_type != request('account_type')) { + $playerDataUrl = Helper::formatHiscoreUrl(request('account_type'), $authStatus->username); + + if (Helper::verifyUrl($playerDataUrl)) { + $authStatus->account_type = request('account_type'); + + $authStatus->save(); + + return redirect(route('show-account-auth'))->with('message', 'Account authentication status deleted!'); + } else { + return redirect()->back()->withErrors('Could not find this Old School RuneScape account! Did you pick correct account type?'); + } + + $authStatus->save(); + } else { + return redirect()->back()->withErrors('This account is already registered as '.Helper::formatAccountTypeName(request('account_type')).'!'); + } + } else { + return redirect(route('create-account'))->withErrors(['You should register a Old School RuneScape account first!']); + } + } + + public function delete() { + $authStatus = AccountAuthStatus::where('user_id', Auth::user()->id)->where('status', '!=', 'success')->first(); + + $authStatus->delete(); + + return redirect(route('create-account'))->with('message', 'Account authentication status deleted!'); + } +} diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index d21ce469..1abc02e3 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -4,17 +4,10 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; -use Illuminate\Support\Facades\DB; -use Carbon\Carbon; - -use App\Helpers\Helper; use App\Account; -use App\Collection; use App\AccountAuthStatus; -use App\Boss\DagannothKings; - class AccountController extends Controller { /** @@ -37,10 +30,9 @@ public function index() { */ public function create() { if (Auth::check()) { - if (Auth::user()->account->first()) { - return view('account.create'); + if (AccountAuthStatus::where('user_id', Auth::user()->id)->where('status', '!=', 'success')->first()) { // TODO limit amount of account links setting - //return redirect(route('home'))->withErrors('This profile has already been linked to a Old School RuneScape account!'); + return redirect(route('show-account-auth'))->withErrors('You already have a pending status! You have to link this Old School RuneScape account to your RuneManager user before you can access this feature.'); } else { return view('account.create'); } @@ -49,50 +41,6 @@ public function create() { } } - /** - * Verifies incoming account registration request. - * - * @return - */ - public function createAccountAuthStatus() { - if (Auth::check()) { - request()->validate([ - 'username' => ['required', 'string', 'min:1', 'max:13'], - ]); - - if (AccountAuthStatus::where('username', request('username'))->count() == 0) { - if (Account::where('username', request('username'))->first()) { - if (Account::where('user_id', Auth::user()->id)->first()) { - return redirect()->back()->withErrors('You have already linked this account to your profile!'); - } - - return redirect()->back()->withErrors('This account has already been linked to another profile!'); - } else { - $playerDataUrl = 'https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws?player='.str_replace(' ', '%20', request('username')); - - if (Helper::verifyUrl($playerDataUrl)) { - $authStatus = new AccountAuthStatus; - - $authStatus->user_id = Auth::user()->id; - $authStatus->username = request('username'); - $authStatus->code = substr(md5(uniqid(mt_rand(), true)), 0, 8); - $authStatus->status = "pending"; - - $authStatus->save(); - - return view('account.auth', compact('authStatus')); - } else { - return redirect()->back()->withErrors('Could not find this Old School RuneScape account!'); - } - } - } else { - return redirect()->back()->withErrors('This account already has a pending status!'); - } - } else { - return redirect(route('login'))->withErrors(['You have to log in before linking a Old School RuneScape account!']); - } - } - /** * Show a specific account and skills data from a URL request. * diff --git a/app/Http/Controllers/Api/AccountController.php b/app/Http/Controllers/Api/AccountController.php index d5ff8739..0cb8b79f 100644 --- a/app/Http/Controllers/Api/AccountController.php +++ b/app/Http/Controllers/Api/AccountController.php @@ -5,6 +5,7 @@ use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; +use Illuminate\Validation\Rule; use Carbon\Carbon; @@ -34,103 +35,104 @@ public function show($accountUsername) { * @return */ public function store($accountUsername) { - $accountAuthStatus = AccountAuthStatus::where([ - ['username', $accountUsername], - ['status', 'pending'] - ])->first(); - - if ($accountAuthStatus) { - if (in_array(request('type'), ['NORMAL', 'IRONMAN', 'HARDCORE', 'ULTIMATE'], true)) { - if (request('code') === $accountAuthStatus->code) { - $playerDataUrl = 'https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws?player='.str_replace(' ', '%20', $accountUsername); - - /* Get the $playerDataUrl file content. */ - $getPlayerData = file_get_contents($playerDataUrl); - - /* Fetch the content from $playerDataUrl. */ - $playerStats = explode("\n", $getPlayerData); - - /* Convert the CSV file of player stats into an array */ - $playerData = []; - foreach ($playerStats as $playerStat) { - $playerData[] = str_getcsv($playerStat); - } + if (in_array(request('account_type'), Helper::listAccountTypes(), true)) { + $authStatus = AccountAuthStatus::where('username', $accountUsername)->where('status', 'pending')->first(); + + if ($authStatus) { + if (request('account_type') === $authStatus->account_type) { + if (request('code') === $authStatus->code) { + $playerDataUrl = 'https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws?player='.str_replace(' ', '%20', $accountUsername); + + /* Get the $playerDataUrl file content. */ + $getPlayerData = file_get_contents($playerDataUrl); - $account = Account::create([ - 'user_id' => $accountAuthStatus->user_id, - 'type' => strtolower(request('type')), - 'username' => $accountUsername, - 'rank' => $playerData[0][0], - 'level' => $playerData[0][1], - 'xp' => $playerData[0][2] - ]); - - $skills = Helper::listSkills(); - - for ($i = 0; $i < count($skills); $i++) { - DB::table($skills[$i])->insert([ - 'account_id' => $account->id, - 'rank' => ($playerData[$i+1][0] >= 1 ? $playerData[$i+1][0] : 0), - 'level' => $playerData[$i+1][1], - 'xp' => ($playerData[$i+1][2] >= 0 ? $playerData[$i+1][2] : 0), - 'created_at' => Carbon::now(), - 'updated_at' => Carbon::now() + /* Fetch the content from $playerDataUrl. */ + $playerStats = explode("\n", $getPlayerData); + + /* Convert the CSV file of player stats into an array */ + $playerData = []; + foreach ($playerStats as $playerStat) { + $playerData[] = str_getcsv($playerStat); + } + + $account = Account::create([ + 'user_id' => $authStatus->user_id, + 'account_type' => request('account_type'), + 'username' => $accountUsername, + 'rank' => $playerData[0][0], + 'level' => $playerData[0][1], + 'xp' => $playerData[0][2] ]); - } - $clueScrollAmount = count(Helper::listClueScrollTiers()); + $skills = Helper::listSkills(); + + for ($i = 0; $i < count($skills); $i++) { + DB::table($skills[$i])->insert([ + 'account_id' => $account->id, + 'rank' => ($playerData[$i+1][0] >= 1 ? $playerData[$i+1][0] : 0), + 'level' => $playerData[$i+1][1], + 'xp' => ($playerData[$i+1][2] >= 0 ? $playerData[$i+1][2] : 0), + 'created_at' => Carbon::now(), + 'updated_at' => Carbon::now() + ]); + } - $bosses = Helper::listBosses(); + $clueScrollAmount = count(Helper::listClueScrollTiers()); - $bossCounter = 0; + $bosses = Helper::listBosses(); - $dksKillCount = 0; + $bossCounter = 0; - for ($i = (count($skills) + $clueScrollAmount + 4); $i < (count($skills) + $clueScrollAmount + 4 + count($bosses)); $i++) { - $collection = Collection::findByName($bosses[$bossCounter]); + $dksKillCount = 0; - $collectionLoot = new $collection->model; + for ($i = (count($skills) + $clueScrollAmount + 4); $i < (count($skills) + $clueScrollAmount + 4 + count($bosses)); $i++) { + $collection = Collection::findByName($bosses[$bossCounter]); - $collectionLoot->account_id = $account->id; - $collectionLoot->kill_count = ($playerData[$i+1][1] >= 0 ? $playerData[$i+1][1] : 0); - $collectionLoot->rank = ($playerData[$i+1][0] >= 0 ? $playerData[$i+1][0] : 0); + $collectionLoot = new $collection->model; - if (in_array($bosses[$bossCounter], ['dagannoth prime', 'dagannoth rex', 'dagannoth supreme'], true)) { - $dksKillCount += ($playerData[$i+1][1] >= 0 ? $playerData[$i+1][1] : 0); - } + $collectionLoot->account_id = $account->id; + $collectionLoot->kill_count = ($playerData[$i+1][1] >= 0 ? $playerData[$i+1][1] : 0); + $collectionLoot->rank = ($playerData[$i+1][0] >= 0 ? $playerData[$i+1][0] : 0); - $collectionLoot->save(); + if (in_array($bosses[$bossCounter], ['dagannoth prime', 'dagannoth rex', 'dagannoth supreme'], true)) { + $dksKillCount += ($playerData[$i+1][1] >= 0 ? $playerData[$i+1][1] : 0); + } - $bossCounter++; - } + $collectionLoot->save(); + + $bossCounter++; + } - /** - * Since there are no official total kill count hiscore for - * DKS' and we are going to retrieve loot for them from the - * collection log, we have to manually create a table. - * This might also happen with other bosses in the future. - */ - $collectionLoot = new \App\Boss\DagannothKings; + /** + * Since there are no official total kill count hiscore for + * DKS' and we are going to retrieve loot for them from the + * collection log, we have to manually create a table. + * This might also happen with other bosses in the future. + */ + $collectionLoot = new \App\Boss\DagannothKings; - $collectionLoot->account_id = $account->id; - $collectionLoot->kill_count = $dksKillCount; + $collectionLoot->account_id = $account->id; + $collectionLoot->kill_count = $dksKillCount; - $collectionLoot->save(); + $collectionLoot->save(); - $accountAuthStatus->status = "success"; + $authStatus->status = "success"; - $accountAuthStatus->save(); + $authStatus->save(); - return response()->json("Success", 200); - // return redirect(route('home'))->with('message', 'Old School RuneScape account "'.request('username').'" linked!'); + return response()->json("Account successfully linked!", 200); + // return redirect(route('home'))->with('message', 'Old School RuneScape account "'.request('username').'" linked!'); + } else { + return response()->json("Invalid code", 202); + } } else { - return response()->json("Invalid code", 401); + return response()->json("This account is registered as ".Helper::formatAccountTypeName($authStatus->account_type)", not ".request('account_type'), 202); } } else { - return response()->json("Not a supported account type", 202); + return response()->json("This account has no pending status", 202); } } else { - return response()->json("This account has no pending status", 202); + return response()->json("Not a supported account type. Valid account types: ".implode(", ", str_replace('_', ' ', Helper::listAccountTypes())), 202); } } } diff --git a/app/User.php b/app/User.php index 49021cc7..adbe6c59 100644 --- a/app/User.php +++ b/app/User.php @@ -40,4 +40,8 @@ class User extends Authenticatable public function account() { return $this->hasMany(Account::class); } + + public function authStatus() { + return $this->hasOne(AccountAuthStatus::class); + } } diff --git a/database/migrations/2020_08_14_225333_create_accounts_table.php b/database/migrations/2020_08_14_225333_create_accounts_table.php index bd857f9d..39b8953b 100644 --- a/database/migrations/2020_08_14_225333_create_accounts_table.php +++ b/database/migrations/2020_08_14_225333_create_accounts_table.php @@ -4,6 +4,8 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; +use App\Helpers\Helper; + class CreateAccountsTable extends Migration { /** @@ -16,7 +18,7 @@ public function up() Schema::create('accounts', function (Blueprint $table) { $table->id(); $table->integer('user_id')->unsigned(); - $table->enum('type', ['normal', 'ironman', 'hardcore', 'ultimate']); + $table->enum('account_type', Helper::listAccountTypes()); $table->string('username', 13); $table->integer('rank')->default(0); $table->integer('level')->default(32); // Minimum total level diff --git a/database/migrations/2020_09_01_093912_create_account_auth_statuses_table.php b/database/migrations/2020_09_01_093912_create_account_auth_statuses_table.php index 6f5e4598..a5770dbe 100644 --- a/database/migrations/2020_09_01_093912_create_account_auth_statuses_table.php +++ b/database/migrations/2020_09_01_093912_create_account_auth_statuses_table.php @@ -4,6 +4,8 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; +use App\Helpers\Helper; + class CreateAccountAuthStatusesTable extends Migration { /** @@ -16,6 +18,7 @@ public function up() Schema::create('account_auth_statuses', function (Blueprint $table) { $table->id(); $table->integer('user_id')->unsigned(); + $table->enum('account_type', Helper::listAccountTypes()); $table->string('username', 13); $table->string('code', 8); $table->enum('status', ['pending', 'success', 'failed', 'expired']); diff --git a/public/images/group.png b/public/images/group_ironman.png similarity index 100% rename from public/images/group.png rename to public/images/group_ironman.png diff --git a/public/images/hardcore.png b/public/images/hardcore_ironman.png similarity index 100% rename from public/images/hardcore.png rename to public/images/hardcore_ironman.png diff --git a/public/images/ultimate.png b/public/images/ultimate_ironman.png similarity index 100% rename from public/images/ultimate.png rename to public/images/ultimate_ironman.png diff --git a/resources/views/account/auth.blade.php b/resources/views/account/auth.blade.php index fdfc3d9b..1b2d610e 100644 --- a/resources/views/account/auth.blade.php +++ b/resources/views/account/auth.blade.php @@ -5,16 +5,60 @@ @endsection @section('content') -

Status pending...

+

Account authentication status for:

-

Code: {{ $authStatus->code }}

+

{{ $authStatus->username }}

-
+
+ + +
+ {{ ucfirst($authStatus->status) }} +
+
+ +
+ + +
+ {{ $authStatus->code }} +
+
+ + + @csrf + @method('PATCH') + +
+ + +
+ {{ Helper::formatAccountTypeName($authStatus->account_type) }} icon {{ Helper::formatAccountTypeName($authStatus->account_type) }} + +
+
+ +
+ +
+ +
+
+
+
+
+ +
@csrf + @method('DELETE')
- +
diff --git a/resources/views/account/create.blade.php b/resources/views/account/create.blade.php index 3288f08f..1a7270b6 100644 --- a/resources/views/account/create.blade.php +++ b/resources/views/account/create.blade.php @@ -7,7 +7,7 @@ @section('content')

{{ __('title.create-member') }}

-
+ @csrf
@@ -25,49 +25,29 @@
- + -
-
- -
- -
- -
- -
- -
- -
- -
- -
- -
+
+ @foreach (Helper::listAccountTypes() as $accountType) + @if ($accountType === 'normal') +
+ +
+ @else +
+ +
+ @endif + @endforeach - @error('mode') + @error('accountType') {{ $message }} diff --git a/routes/api.php b/routes/api.php index 3967dcc4..01f7d38f 100644 --- a/routes/api.php +++ b/routes/api.php @@ -25,7 +25,7 @@ Route::prefix('/account')->group(function () { Route::get('/{account}', 'Api\AccountController@show')->name('show-account'); - Route::post('/{account}', 'Api\AccountController@store')->name('authenticate-account'); + Route::post('/{account}/authenticate', 'Api\AccountController@store')->name('authenticate-account'); Route::get('/{accountUsername}/collection/{collectionName}', 'Api\AccountCollectionController@show')->name('show-account-collection'); Route::put('/{accountUsername}/collection/{collectionName}', 'Api\AccountCollectionController@update')->name('update-account-collection'); diff --git a/routes/web.php b/routes/web.php index a873e3b7..f44d23d3 100644 --- a/routes/web.php +++ b/routes/web.php @@ -23,9 +23,13 @@ Route::get('/account', 'AccountController@index')->name('account'); Route::post('/account', 'AccountController@search')->name('search-account'); Route::get('/account/create', 'AccountController@create')->name('create-account'); -Route::post('/account/create', 'AccountController@createAccountAuthStatus')->name('store-account'); Route::get('/account/{id}', 'AccountController@show')->name('show-account'); +Route::get('/authenticate', 'AccountAuthController@index')->name('show-account-auth'); +Route::post('/authenticate', 'AccountAuthController@create')->name('create-account-auth'); +Route::patch('/authenticate', 'AccountAuthController@updateAccountType')->name('update-account-auth'); +Route::delete('/authenticate', 'AccountAuthController@delete')->name('delete-account-auth'); + /*==========User Controller=============*/ Route::get('/user/edit', 'UserController@edit')->name('edit-user'); Route::patch('/user/edit', 'UserController@update')->name('update-user'); From 3b0d8e3fd043d1381ed5365285ccb9e58b3732f9 Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 28 Oct 2020 00:47:37 +0100 Subject: [PATCH 03/80] Cleanup, Loot Api Controller and text Seperated Loot and Collection controller Made user username unique Added FAQ to Authenticate page --- .../Controllers/AccountAuthController.php | 4 +- .../Api/AccountCollectionController.php | 33 +----- .../Controllers/Api/AccountController.php | 105 +++++++++--------- .../Controllers/Api/AccountLootController.php | 61 ++++++++++ .../2014_10_12_000000_create_users_table.php | 2 +- resources/views/account/auth.blade.php | 40 +++++++ routes/api.php | 5 +- 7 files changed, 163 insertions(+), 87 deletions(-) create mode 100644 app/Http/Controllers/Api/AccountLootController.php diff --git a/app/Http/Controllers/AccountAuthController.php b/app/Http/Controllers/AccountAuthController.php index 051466ae..ed3355ef 100644 --- a/app/Http/Controllers/AccountAuthController.php +++ b/app/Http/Controllers/AccountAuthController.php @@ -15,7 +15,7 @@ class AccountAuthController extends Controller { public function index() { if (Auth::check()) { - $authStatus = AccountAuthStatus::where('user_id', Auth::user()->id)->where('status', '!=', 'success')->first(); + $authStatus = AccountAuthStatus::with('user')->where('user_id', Auth::user()->id)->where('status', '!=', 'success')->first(); if ($authStatus) { return view('account.auth', compact('authStatus')); @@ -91,8 +91,6 @@ public function updateAccountType() { } else { return redirect()->back()->withErrors('Could not find this Old School RuneScape account! Did you pick correct account type?'); } - - $authStatus->save(); } else { return redirect()->back()->withErrors('This account is already registered as '.Helper::formatAccountTypeName(request('account_type')).'!'); } diff --git a/app/Http/Controllers/Api/AccountCollectionController.php b/app/Http/Controllers/Api/AccountCollectionController.php index 2b6569a0..332adc8e 100644 --- a/app/Http/Controllers/Api/AccountCollectionController.php +++ b/app/Http/Controllers/Api/AccountCollectionController.php @@ -89,38 +89,9 @@ public function update($accountUsername, $collectionName, Request $request) { if ($collection) { $collectionLog = $collection->model::where('account_id', $account->id)->first(); - if ($collectionLog) { - $oldValues = $collectionLog->getAttributes(); // Get old data - //array_splice($oldValues, count($oldValues) - 2, 2); // Remove created_at and updated_at - - $newValues = $request->all(); - - $sums = []; - - $sums["kill_count"] = $oldValues["kill_count"] + 1; + $collectionLog->update($request->all()); - $uniques = $oldValues["obtained"]; - - // Merge old data and new data and sum the total of common keys - foreach (array_keys($newValues + $oldValues) as $lootType) { - if (isset($newValues[$lootType]) && isset($oldValues[$lootType])) { - // If unique loot is detected, increase the total amount of uniques obtained by 1 - if ($oldValues[$lootType] == 0) { - $uniques++; - } - - $sums[$lootType] = (isset($newValues[$lootType]) ? $newValues[$lootType] : 0) + (isset($oldValues) ? $oldValues[$lootType] : 0); - } - } - - $sums["obtained"] = $uniques; - - $collectionLog->update($sums); - - return response()->json($collectionLog, 201); - } else { - return response()->json("This account does not have any registered loot for " . $collection->name, 404); - } + return response()->json($collectionLog, 201); } else { return response()->json("This collection could not be found", 404); } diff --git a/app/Http/Controllers/Api/AccountController.php b/app/Http/Controllers/Api/AccountController.php index 0cb8b79f..cca1e908 100644 --- a/app/Http/Controllers/Api/AccountController.php +++ b/app/Http/Controllers/Api/AccountController.php @@ -55,78 +55,81 @@ public function store($accountUsername) { $playerData[] = str_getcsv($playerStat); } - $account = Account::create([ - 'user_id' => $authStatus->user_id, - 'account_type' => request('account_type'), - 'username' => $accountUsername, - 'rank' => $playerData[0][0], - 'level' => $playerData[0][1], - 'xp' => $playerData[0][2] - ]); - - $skills = Helper::listSkills(); - - for ($i = 0; $i < count($skills); $i++) { - DB::table($skills[$i])->insert([ - 'account_id' => $account->id, - 'rank' => ($playerData[$i+1][0] >= 1 ? $playerData[$i+1][0] : 0), - 'level' => $playerData[$i+1][1], - 'xp' => ($playerData[$i+1][2] >= 0 ? $playerData[$i+1][2] : 0), - 'created_at' => Carbon::now(), - 'updated_at' => Carbon::now() + if ($playerData[0][0]) { + $account = Account::create([ + 'user_id' => $authStatus->user_id, + 'account_type' => request('account_type'), + 'username' => $accountUsername, + 'rank' => $playerData[0][0], + 'level' => $playerData[0][1], + 'xp' => $playerData[0][2] ]); - } - $clueScrollAmount = count(Helper::listClueScrollTiers()); + $skills = Helper::listSkills(); + + for ($i = 0; $i < count($skills); $i++) { + DB::table($skills[$i])->insert([ + 'account_id' => $account->id, + 'rank' => ($playerData[$i+1][0] >= 1 ? $playerData[$i+1][0] : 0), + 'level' => $playerData[$i+1][1], + 'xp' => ($playerData[$i+1][2] >= 0 ? $playerData[$i+1][2] : 0), + 'created_at' => Carbon::now(), + 'updated_at' => Carbon::now() + ]); + } - $bosses = Helper::listBosses(); + $clueScrollAmount = count(Helper::listClueScrollTiers()); - $bossCounter = 0; + $bosses = Helper::listBosses(); - $dksKillCount = 0; + $bossCounter = 0; - for ($i = (count($skills) + $clueScrollAmount + 4); $i < (count($skills) + $clueScrollAmount + 4 + count($bosses)); $i++) { - $collection = Collection::findByName($bosses[$bossCounter]); + $dksKillCount = 0; - $collectionLoot = new $collection->model; + for ($i = (count($skills) + $clueScrollAmount + 4); $i < (count($skills) + $clueScrollAmount + 4 + count($bosses)); $i++) { + $collection = Collection::findByName($bosses[$bossCounter]); - $collectionLoot->account_id = $account->id; - $collectionLoot->kill_count = ($playerData[$i+1][1] >= 0 ? $playerData[$i+1][1] : 0); - $collectionLoot->rank = ($playerData[$i+1][0] >= 0 ? $playerData[$i+1][0] : 0); + $collectionLoot = new $collection->model; - if (in_array($bosses[$bossCounter], ['dagannoth prime', 'dagannoth rex', 'dagannoth supreme'], true)) { - $dksKillCount += ($playerData[$i+1][1] >= 0 ? $playerData[$i+1][1] : 0); - } + $collectionLoot->account_id = $account->id; + $collectionLoot->kill_count = ($playerData[$i+1][1] >= 0 ? $playerData[$i+1][1] : 0); + $collectionLoot->rank = ($playerData[$i+1][0] >= 0 ? $playerData[$i+1][0] : 0); - $collectionLoot->save(); + if (in_array($bosses[$bossCounter], ['dagannoth prime', 'dagannoth rex', 'dagannoth supreme'], true)) { + $dksKillCount += ($playerData[$i+1][1] >= 0 ? $playerData[$i+1][1] : 0); + } - $bossCounter++; - } + $collectionLoot->save(); - /** - * Since there are no official total kill count hiscore for - * DKS' and we are going to retrieve loot for them from the - * collection log, we have to manually create a table. - * This might also happen with other bosses in the future. - */ - $collectionLoot = new \App\Boss\DagannothKings; + $bossCounter++; + } - $collectionLoot->account_id = $account->id; - $collectionLoot->kill_count = $dksKillCount; + /** + * Since there are no official total kill count hiscore for + * DKS' and we are going to retrieve loot for them from the + * collection log, we have to manually create a table. + * This might also happen with other bosses in the future. + */ + $collectionLoot = new \App\Boss\DagannothKings; - $collectionLoot->save(); + $collectionLoot->account_id = $account->id; + $collectionLoot->kill_count = $dksKillCount; - $authStatus->status = "success"; + $collectionLoot->save(); - $authStatus->save(); + $authStatus->status = "success"; - return response()->json("Account successfully linked!", 200); - // return redirect(route('home'))->with('message', 'Old School RuneScape account "'.request('username').'" linked!'); + $authStatus->save(); + + return response()->json("Account successfully authenticated!", 200); + } else { + return response()->json("Could not fetch player data from hiscores", 202); + } } else { return response()->json("Invalid code", 202); } } else { - return response()->json("This account is registered as ".Helper::formatAccountTypeName($authStatus->account_type)", not ".request('account_type'), 202); + return response()->json("This account is registered as ".Helper::formatAccountTypeName($authStatus->account_type).", not ".request('account_type'), 202); } } else { return response()->json("This account has no pending status", 202); diff --git a/app/Http/Controllers/Api/AccountLootController.php b/app/Http/Controllers/Api/AccountLootController.php new file mode 100644 index 00000000..23e37e0f --- /dev/null +++ b/app/Http/Controllers/Api/AccountLootController.php @@ -0,0 +1,61 @@ +first(); + + if ($account) { + $collection = Collection::findByName($collectionName); + + if ($collection) { + $collectionLog = $collection->model::where('account_id', $account->id)->first(); + + if ($collectionLog) { + $oldValues = $collectionLog->getAttributes(); // Get old data + //array_splice($oldValues, count($oldValues) - 2, 2); // Remove created_at and updated_at + + $newValues = $request->all(); + + $sums = []; + + $sums["kill_count"] = $oldValues["kill_count"] + 1; + + $uniques = $oldValues["obtained"]; + + // Merge old data and new data and sum the total of common keys + foreach (array_keys($newValues + $oldValues) as $lootType) { + if (isset($newValues[$lootType]) && isset($oldValues[$lootType])) { + // If unique loot is detected, increase the total amount of uniques obtained by 1 + if ($oldValues[$lootType] == 0) { + $uniques++; + } + + $sums[$lootType] = (isset($newValues[$lootType]) ? $newValues[$lootType] : 0) + (isset($oldValues) ? $oldValues[$lootType] : 0); + } + } + + $sums["obtained"] = $uniques; + + $collectionLog->update($sums); + + return response()->json($collectionLog, 201); + } else { + return response()->json("This account does not have any registered loot for " . $collection->name, 404); + } + } else { + return response()->json("This collection could not be found", 404); + } + } else { + return response()->json("This account could not be found", 404); + } + } +} diff --git a/database/migrations/2014_10_12_000000_create_users_table.php b/database/migrations/2014_10_12_000000_create_users_table.php index 4fdc4dd9..dc49863b 100644 --- a/database/migrations/2014_10_12_000000_create_users_table.php +++ b/database/migrations/2014_10_12_000000_create_users_table.php @@ -16,7 +16,7 @@ public function up() Schema::create('users', function (Blueprint $table) { $table->id(); $table->uuid('uuid')->default('b5d1a339-af63-44d1-bd18-956083157134'); - $table->string('name'); + $table->string('name')->unique(); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); diff --git a/resources/views/account/auth.blade.php b/resources/views/account/auth.blade.php index 1b2d610e..679ea20e 100644 --- a/resources/views/account/auth.blade.php +++ b/resources/views/account/auth.blade.php @@ -62,4 +62,44 @@
+ +

How to authenticate:

+ +
    +
  1. Make sure you have the RuneManager plugin enabled
  2. +
  3. Enter your RuneManager user credentials in the RuneManager plugin configurations
  4. +
  5. Log in on your Old School RuneScape account
  6. +
  7. Type: !auth {{ $authStatus->code }}
  8. +
  9. You should get the response:
    + Attempting to authenticate account {{ $authStatus->username }} to user {{ $authStatus->user->name }}
  10. +
  11. And then:
    + Account successfully authenticated!
  12. +
+ +

Other responses mean:

+ +
    +
  • + Not a supported account type. Valid account types: normal, ironman, hardcore ironman, ultimate ironman
    + This means you are attempting to authenticate the account on an unsupported game mode such as DMM, Leagues etc.
    + To fix this you have to log in to a normal world +
  • +
  • + This account has no pending status
    + This means this account has (or has not successfully) already been authenticated to RuneManager +
  • +
  • + This account is registered as <account type>, not <account type>
    + This means you are attempting to authenticate the account with a different account type than the registered account type
    + To fix this you can update the account type above +
  • +
  • + Invalid code
    + This means you have most likely written the code wrong. Try again +
  • +
  • + Could not fetch player data from hiscores
    + This means RuneManager was not able to fetch player hiscores from Old School RuneScape. This is most likely an error on the Old School hiscore server +
  • +
@endsection \ No newline at end of file diff --git a/routes/api.php b/routes/api.php index 01f7d38f..6c638ab2 100644 --- a/routes/api.php +++ b/routes/api.php @@ -27,8 +27,11 @@ Route::get('/{account}', 'Api\AccountController@show')->name('show-account'); Route::post('/{account}/authenticate', 'Api\AccountController@store')->name('authenticate-account'); + // Route::get('/{accountUsername}/loot/{collectionName}', 'Api\AccountCollectionController@show')->name('show-account-collection'); + Route::put('/{accountUsername}/loot/{collectionName}', 'Api\AccountLootController@update')->name('update-account-loot'); + Route::get('/{accountUsername}/collection/{collectionName}', 'Api\AccountCollectionController@show')->name('show-account-collection'); - Route::put('/{accountUsername}/collection/{collectionName}', 'Api\AccountCollectionController@update')->name('update-account-collection'); + Route::post('/{accountUsername}/collection/{collectionName}', 'Api\AccountCollectionController@update')->name('update-account-collection'); }); Route::prefix('/collection')->group(function () { From 6bd521ab986f9be4fb9b5a27c2debab70e0fb225 Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 28 Oct 2020 11:35:35 +0100 Subject: [PATCH 04/80] AccountUpdate command --- app/Console/Commands/AccountUpdate.php | 129 +++++++++++++++++++++++++ app/Console/Kernel.php | 5 +- 2 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 app/Console/Commands/AccountUpdate.php diff --git a/app/Console/Commands/AccountUpdate.php b/app/Console/Commands/AccountUpdate.php new file mode 100644 index 00000000..ad013b68 --- /dev/null +++ b/app/Console/Commands/AccountUpdate.php @@ -0,0 +1,129 @@ +username); + + /* Get the $playerDataUrl file content. */ + $getPlayerData = file_get_contents($playerDataUrl); + + /* Fetch the content from $playerDataUrl. */ + $playerStats = explode("\n", $getPlayerData); + + /* Convert the CSV file of player stats into an array */ + $playerData = []; + foreach ($playerStats as $playerStat) { + $playerData[] = str_getcsv($playerStat); + } + + if ($playerData[0][0]) { + if ($account->xp != $playerData[0][2]) { + $this->info(sprintf("Detected %s in database with outdated data! Updating...", $account->username)); + + $account->rank = $playerData[0][0]; + $account->level = $playerData[0][1]; + $account->xp = $playerData[0][2]; + + $account->update(); + + $skills = Helper::listSkills(); + + for ($i = 0; $i < count($skills); $i++) { + DB::table($skills[$i]) + ->where('account_id', $account->id) + ->update(['rank' => ($playerData[$i+1][0] >= 1 ? $playerData[$i+1][0] : 0), 'level' => $playerData[$i+1][1], 'xp' => ($playerData[$i+1][2] >= 0 ? $playerData[$i+1][2] : 0)]); + } + + $clueScrollAmount = count(Helper::listClueScrollTiers()); + + $bosses = Helper::listBosses(); + + $bossCounter = 0; + + $dksKillCount = 0; + + for ($i = (count($skills) + $clueScrollAmount + 4); $i < (count($skills) + $clueScrollAmount + 4 + count($bosses)); $i++) { + $collection = Collection::findByName($bosses[$bossCounter]); + + $collection = $collection->model::where('account_id', $account->id)->first(); + + $collection->kill_count = ($playerData[$i+1][1] >= 0 ? $playerData[$i+1][1] : 0); + $collection->rank = ($playerData[$i+1][0] >= 0 ? $playerData[$i+1][0] : 0); + + $collection->update(); + + if (in_array($bosses[$bossCounter], ['dagannoth prime', 'dagannoth rex', 'dagannoth supreme'], true)) { + $dksKillCount += ($playerData[$i+1][1] >= 0 ? $playerData[$i+1][1] : 0); + } + + $bossCounter++; + } + + /** + * Since there are no official total kill count hiscore for + * DKS' and we are going to retrieve loot for them from the + * collection log, we have to manually create a table. + * This might also happen with other bosses in the future. + */ + $dks = \App\Boss\DagannothKings::where('account_id', $account->id)->first();; + + $dks->kill_count = $dksKillCount; + + $dks->update(); + + $this->info(sprintf("Updated %s!", $account->username)); + } else { + $this->info(sprintf("No outdated data for %s! Not updating...", $account->username)); + } + } else { + $this->info(sprintf("Could not fetch player data from hiscores")); + } + } + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 69914e99..0c7f9ab9 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -13,7 +13,7 @@ class Kernel extends ConsoleKernel * @var array */ protected $commands = [ - // + Commands\AccountUpdate::class, ]; /** @@ -24,7 +24,8 @@ class Kernel extends ConsoleKernel */ protected function schedule(Schedule $schedule) { - // $schedule->command('inspire')->hourly(); + $schedule->command('account:update') + ->hourly(); } /** From ee540dfb8d81dd8941ed1c87d11cdb08f4034d0e Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 28 Oct 2020 14:12:06 +0100 Subject: [PATCH 05/80] Better code format --- resources/views/account/auth.blade.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/resources/views/account/auth.blade.php b/resources/views/account/auth.blade.php index 679ea20e..cdab53d0 100644 --- a/resources/views/account/auth.blade.php +++ b/resources/views/account/auth.blade.php @@ -21,7 +21,7 @@
- {{ $authStatus->code }} + {{ $authStatus->code }}
@@ -69,11 +69,15 @@
  • Make sure you have the RuneManager plugin enabled
  • Enter your RuneManager user credentials in the RuneManager plugin configurations
  • Log in on your Old School RuneScape account
  • -
  • Type: !auth {{ $authStatus->code }}
  • +
  • Type in chat:
    + !auth {{ $authStatus->code }} +
  • You should get the response:
    - Attempting to authenticate account {{ $authStatus->username }} to user {{ $authStatus->user->name }}
  • + Attempting to authenticate account {{ $authStatus->username }} to user {{ $authStatus->user->name }} +
  • And then:
    - Account successfully authenticated!
  • + Account successfully authenticated! +

    Other responses mean:

    From 3faf9cd13d9f38d3b2b60a931b773c2cd2e5de03 Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 30 Oct 2020 23:37:27 +0100 Subject: [PATCH 06/80] API Oauth authentication --- app/Account.php | 2 +- .../Api/AccountCollectionController.php | 20 +- .../Controllers/Api/AccountController.php | 47 ++-- .../Controllers/Api/AccountLootController.php | 12 +- app/Http/Controllers/Api/UserController.php | 51 ++++ app/Providers/AuthServiceProvider.php | 1 + composer.lock | 245 +----------------- config/app.php | 3 +- config/auth.php | 2 +- routes/api.php | 33 +-- 10 files changed, 135 insertions(+), 281 deletions(-) create mode 100644 app/Http/Controllers/Api/UserController.php diff --git a/app/Account.php b/app/Account.php index 9f4ab359..0d404db0 100644 --- a/app/Account.php +++ b/app/Account.php @@ -12,7 +12,7 @@ class Account extends Model * @var array */ protected $fillable = [ - 'user_id', 'type', 'username', 'rank', 'level', 'xp', 'private' + 'user_id', 'account_type', 'username', 'rank', 'level', 'xp' ]; public function user() { diff --git a/app/Http/Controllers/Api/AccountCollectionController.php b/app/Http/Controllers/Api/AccountCollectionController.php index 332adc8e..f6e92484 100644 --- a/app/Http/Controllers/Api/AccountCollectionController.php +++ b/app/Http/Controllers/Api/AccountCollectionController.php @@ -70,18 +70,18 @@ public function show($accountUsername, $collectionName) { if ($collectionLog) { return response()->json($collectionLog, 200); } else { - return response()->json("This account does not have any registered loot for " . $collection->name, 404); + return response("This account does not have any registered loot for " . $collection->name, 404); } } else { - return response()->json("This collection could not be found", 404); + return response("This collection could not be found", 404); } } else { - return response()->json("This account could not be found", 404); + return response("This account is not authenticated with " . auth()->user()->name, 401); } } public function update($accountUsername, $collectionName, Request $request) { - $account = Account::where('username', $accountUsername)->first(); + $account = Account::where('user_id', auth()->user()->id)->where('username', $accountUsername)->first(); if ($account) { $collection = Collection::findByName($collectionName); @@ -89,14 +89,18 @@ public function update($accountUsername, $collectionName, Request $request) { if ($collection) { $collectionLog = $collection->model::where('account_id', $account->id)->first(); - $collectionLog->update($request->all()); + if ($collectionLog) { + $collectionLog->update($request->all()); - return response()->json($collectionLog, 201); + return response()->json($collectionLog, 200); + } else { + return response("This account does not have any registered loot for " . $collection->name, 404); + } } else { - return response()->json("This collection could not be found", 404); + return response("This collection could not be found", 404); } } else { - return response()->json("This account could not be found", 404); + return response("This account is not authenticated with " . auth()->user()->name, 401); } } } diff --git a/app/Http/Controllers/Api/AccountController.php b/app/Http/Controllers/Api/AccountController.php index cca1e908..e2c0f2b3 100644 --- a/app/Http/Controllers/Api/AccountController.php +++ b/app/Http/Controllers/Api/AccountController.php @@ -15,6 +15,9 @@ use App\Collection; use App\Http\Resources\AccountResource; +use Illuminate\Support\Facades\Auth; + +use Illuminate\Support\Facades\Validator; class AccountController extends Controller { @@ -34,14 +37,26 @@ public function show($accountUsername) { * @param string $authCode * @return */ - public function store($accountUsername) { - if (in_array(request('account_type'), Helper::listAccountTypes(), true)) { - $authStatus = AccountAuthStatus::where('username', $accountUsername)->where('status', 'pending')->first(); + public function store(Request $request) { + $validator = Validator::make($request->all(), [ + 'username' => ['required', 'string', 'min:1', 'max:13'], + 'code' => ['required', 'string', 'min:1', 'max:8'], + 'account_type' => ['required', Rule::in(Helper::listAccountTypes())], + ]); + + if ($validator->fails()) { + foreach ($validator->messages()->all() as $value) { + return response($value, 202); + } + } + + $authStatus = AccountAuthStatus::where('username', request('username'))->where('status', 'pending')->first(); - if ($authStatus) { + if ($authStatus) { + if ($authStatus->user_id === auth()->user()->id) { if (request('account_type') === $authStatus->account_type) { if (request('code') === $authStatus->code) { - $playerDataUrl = 'https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws?player='.str_replace(' ', '%20', $accountUsername); + $playerDataUrl = 'https://secure.runescape.com/m=hiscore_oldschool/index_lite.ws?player='.str_replace(' ', '%20', request('username')); /* Get the $playerDataUrl file content. */ $getPlayerData = file_get_contents($playerDataUrl); @@ -59,7 +74,7 @@ public function store($accountUsername) { $account = Account::create([ 'user_id' => $authStatus->user_id, 'account_type' => request('account_type'), - 'username' => $accountUsername, + 'username' => request('username'), 'rank' => $playerData[0][0], 'level' => $playerData[0][1], 'xp' => $playerData[0][2] @@ -110,32 +125,32 @@ public function store($accountUsername) { * collection log, we have to manually create a table. * This might also happen with other bosses in the future. */ - $collectionLoot = new \App\Boss\DagannothKings; + $dks = new \App\Boss\DagannothKings; - $collectionLoot->account_id = $account->id; - $collectionLoot->kill_count = $dksKillCount; + $dks->account_id = $account->id; + $dks->kill_count = $dksKillCount; - $collectionLoot->save(); + $dks->save(); $authStatus->status = "success"; $authStatus->save(); - return response()->json("Account successfully authenticated!", 200); + return response("Account successfully authenticated!", 201); } else { - return response()->json("Could not fetch player data from hiscores", 202); + return response("Could not fetch player data from hiscores", 203); } } else { - return response()->json("Invalid code", 202); + return response("Invalid code", 202); } } else { - return response()->json("This account is registered as ".Helper::formatAccountTypeName($authStatus->account_type).", not ".request('account_type'), 202); + return response("This account is registered as ".lcfirst(Helper::formatAccountTypeName($authStatus->account_type)).", not ".request('account_type'), 202); } } else { - return response()->json("This account has no pending status", 202); + return response("This account is not linked to your user", 401); } } else { - return response()->json("Not a supported account type. Valid account types: ".implode(", ", str_replace('_', ' ', Helper::listAccountTypes())), 202); + return response("This account has no pending status", 202); } } } diff --git a/app/Http/Controllers/Api/AccountLootController.php b/app/Http/Controllers/Api/AccountLootController.php index 23e37e0f..18b9e295 100644 --- a/app/Http/Controllers/Api/AccountLootController.php +++ b/app/Http/Controllers/Api/AccountLootController.php @@ -11,7 +11,7 @@ class AccountLootController extends Controller { public function update($accountUsername, $collectionName, Request $request) { - $account = Account::where('username', $accountUsername)->first(); + $account = Account::where('user_id', auth()->user()->id)->where('username', $accountUsername)->first(); if ($account) { $collection = Collection::findByName($collectionName); @@ -23,7 +23,7 @@ public function update($accountUsername, $collectionName, Request $request) { $oldValues = $collectionLog->getAttributes(); // Get old data //array_splice($oldValues, count($oldValues) - 2, 2); // Remove created_at and updated_at - $newValues = $request->all(); + $newValues = $request->except(['kill_count', 'rank', 'obtained']); $sums = []; @@ -47,15 +47,15 @@ public function update($accountUsername, $collectionName, Request $request) { $collectionLog->update($sums); - return response()->json($collectionLog, 201); + return response()->json($collectionLog, 200); } else { - return response()->json("This account does not have any registered loot for " . $collection->name, 404); + return response("This account does not have any registered loot for " . $collection->name, 404); } } else { - return response()->json("This collection could not be found", 404); + return response("This collection could not be found", 404); } } else { - return response()->json("This account could not be found", 404); + return response("This account is not authenticated with " . auth()->user()->name, 401); } } } diff --git a/app/Http/Controllers/Api/UserController.php b/app/Http/Controllers/Api/UserController.php new file mode 100644 index 00000000..aaaeee20 --- /dev/null +++ b/app/Http/Controllers/Api/UserController.php @@ -0,0 +1,51 @@ +validate([ + 'name' => ['required', 'string', 'max:255'], + 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], + 'password' => ['required', 'string', 'min:8'], + ]); + + $user = User::create([ + 'name' => $request->name, + 'email' => $request->email, + 'password' => Hash::make($request->password), + ]); + + $accessToken = $user->createToken('accessToken')->accessToken; + + return response()->json(['accessToken' => $accessToken], 200); + } + + public function login(Request $request) { + $login = $request->validate([ + 'name' => ['required', 'string', 'max:255'], + 'password' => ['required', 'string', 'min:8'], + ]); + + if (!Auth::attempt($login)) { + return response()->json('These credentials do not match our records.', 401); + } + + $accessToken = Auth::user()->createToken('authToken')->accessToken; + + return response($accessToken, 200); + } + + public function user() { + return response()->json(['user' => auth()->user()], 200); + } +} diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index a2b0a77a..13029bd9 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -4,6 +4,7 @@ use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Gate; + use Laravel\Passport\Passport; class AuthServiceProvider extends ServiceProvider diff --git a/composer.lock b/composer.lock index e156dc1d..d79dce0e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "628a3b2c934e6dcc88b76a77a0caf696", + "content-hash": "7df55274de8588fb4cbdf169975bcbe5", "packages": [ { "name": "asm89/stack-cors", @@ -898,12 +898,6 @@ "psr-17", "psr-7" ], - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], "time": "2020-07-07T15:34:31+00:00" }, { @@ -956,12 +950,6 @@ "laminas", "zf" ], - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], "time": "2020-05-20T16:45:56+00:00" }, { @@ -1366,16 +1354,6 @@ "JWS", "jwt" ], - "funding": [ - { - "url": "https://github.com/lcobucci", - "type": "github" - }, - { - "url": "https://www.patreon.com/lcobucci", - "type": "patreon" - } - ], "time": "2020-05-22T08:21:12+00:00" }, { @@ -1656,12 +1634,6 @@ "secure", "server" ], - "funding": [ - { - "url": "https://github.com/sephster", - "type": "github" - } - ], "time": "2020-07-01T11:33:50+00:00" }, { @@ -1931,16 +1903,6 @@ "psr-17", "psr-7" ], - "funding": [ - { - "url": "https://github.com/Zegnat", - "type": "github" - }, - { - "url": "https://github.com/nyholm", - "type": "github" - } - ], "time": "2020-05-23T11:29:07+00:00" }, { @@ -2244,20 +2206,6 @@ "x.509", "x509" ], - "funding": [ - { - "url": "https://github.com/terrafrost", - "type": "github" - }, - { - "url": "https://www.patreon.com/phpseclib", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", - "type": "tidelift" - } - ], "time": "2020-07-08T09:08:33+00:00" }, { @@ -3048,21 +2996,7 @@ ], "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-05-27T08:34:37+00:00" + "time": "2020-06-06T08:49:21+00:00" }, { "name": "symfony/error-handler", @@ -3119,21 +3053,7 @@ ], "description": "Symfony ErrorHandler Component", "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-05-30T20:35:19+00:00" + "time": "2020-08-17T10:01:29+00:00" }, { "name": "symfony/event-dispatcher", @@ -3205,21 +3125,7 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-05-20T17:43:50+00:00" + "time": "2020-08-13T14:19:42+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -3281,21 +3187,7 @@ "interoperability", "standards" ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-05-20T17:43:50+00:00" + "time": "2020-07-06T13:23:11+00:00" }, { "name": "symfony/finder", @@ -3405,21 +3297,7 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-06-15T06:52:54+00:00" + "time": "2020-08-17T07:48:54+00:00" }, { "name": "symfony/http-kernel", @@ -3518,21 +3396,7 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-06-15T13:51:38+00:00" + "time": "2020-09-02T08:15:18+00:00" }, { "name": "symfony/mime", @@ -3657,21 +3521,7 @@ "polyfill", "portable" ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-05-12T16:14:59+00:00" + "time": "2020-07-14T12:35:20+00:00" }, { "name": "symfony/polyfill-iconv", @@ -3978,21 +3828,7 @@ "portable", "shim" ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-05-12T16:47:27+00:00" + "time": "2020-07-14T12:35:20+00:00" }, { "name": "symfony/polyfill-php72", @@ -4109,21 +3945,7 @@ "portable", "shim" ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-05-12T16:47:27+00:00" + "time": "2020-07-14T12:35:20+00:00" }, { "name": "symfony/polyfill-php80", @@ -4189,21 +4011,7 @@ "portable", "shim" ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-05-12T16:47:27+00:00" + "time": "2020-07-14T12:35:20+00:00" }, { "name": "symfony/process", @@ -4317,20 +4125,6 @@ "psr-17", "psr-7" ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], "time": "2020-06-25T08:21:47+00:00" }, { @@ -4749,21 +4543,7 @@ "debug", "dump" ], - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2020-05-30T20:35:19+00:00" + "time": "2020-08-17T07:42:30+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -6103,6 +5883,7 @@ "keywords": [ "tokenizer" ], + "abandoned": true, "time": "2019-09-17T06:23:10+00:00" }, { diff --git a/config/app.php b/config/app.php index ac08d12f..773fc450 100644 --- a/config/app.php +++ b/config/app.php @@ -176,6 +176,7 @@ App\Providers\RouteServiceProvider::class, App\Providers\HelperServiceProvider::class, + Laravel\Passport\PassportServiceProvider::class, ], @@ -229,7 +230,7 @@ 'Validator' => Illuminate\Support\Facades\Validator::class, 'View' => Illuminate\Support\Facades\View::class, 'Helper' => App\Helpers\Helper::class, - + 'Pusher' => Pusher\Pusher::class, ], ]; diff --git a/config/auth.php b/config/auth.php index 04c6eec2..6db2705f 100644 --- a/config/auth.php +++ b/config/auth.php @@ -44,7 +44,7 @@ 'api' => [ 'driver' => 'passport', 'provider' => 'users', - 'hash' => false, + // 'hash' => false, ], ], diff --git a/routes/api.php b/routes/api.php index 6c638ab2..eaed4469 100644 --- a/routes/api.php +++ b/routes/api.php @@ -14,28 +14,29 @@ | */ -Route::middleware('auth:api')->get('/user', function (Request $request) { - return $request->user(); +Route::prefix('/user')->group(function() { + Route::post('/register', 'Api\UserController@register')->name('user-register'); + Route::post('/login', 'Api\UserController@login')->name('user-login'); }); -Route::prefix('/hiscore')->group(function () { - Route::get('/skill/{skill}', 'Api\HiscoreController@skill')->name('show-skill-hiscore'); - Route::get('/boss/{skill}', 'Api\HiscoreController@boss')->name('show-boss-hiscore'); -}); +Route::middleware('auth:api')->group(function() { + Route::get('/user', 'Api\UserController@user')->name('user-show'); + Route::post('/authenticate', 'Api\AccountController@store')->name('authenticate'); // Authenticate user -Route::prefix('/account')->group(function () { - Route::get('/{account}', 'Api\AccountController@show')->name('show-account'); - Route::post('/{account}/authenticate', 'Api\AccountController@store')->name('authenticate-account'); + Route::prefix('/account')->group(function () { + Route::put('/{accountUsername}/loot/{collection}', 'Api\AccountLootController@update')->name('account-loot-update'); // Put loot data - updates collection model + Route::post('/{accountUsername}/collection/{collection}', 'Api\AccountCollectionController@update')->name('account-collection-update'); // Post collection data - replaces collection model + }); +}); - // Route::get('/{accountUsername}/loot/{collectionName}', 'Api\AccountCollectionController@show')->name('show-account-collection'); - Route::put('/{accountUsername}/loot/{collectionName}', 'Api\AccountLootController@update')->name('update-account-loot'); +Route::get('/account/{account}', 'Api\AccountController@show')->name('account-show'); +Route::get('/account/{accountUsername}/collection/{collectionName}', 'Api\AccountCollectionController@show')->name('account-collection-show'); - Route::get('/{accountUsername}/collection/{collectionName}', 'Api\AccountCollectionController@show')->name('show-account-collection'); - Route::post('/{accountUsername}/collection/{collectionName}', 'Api\AccountCollectionController@update')->name('update-account-collection'); +Route::prefix('/hiscore')->group(function () { + Route::get('/skill/{skill}', 'Api\HiscoreController@skill')->name('hiscore-skill-show'); + Route::get('/boss/{skill}', 'Api\HiscoreController@boss')->name('hiscore-boss-show'); }); Route::prefix('/collection')->group(function () { - // Route::middleware('auth:api')->group(function () { - Route::get('/{collectionType}', 'CollectionController@list'); - // }); + Route::get('/{collectionType}', 'CollectionController@list'); }); \ No newline at end of file From b9dfca9dc34ba7fb67c1d28dedd3731487aa0756 Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 30 Oct 2020 23:48:37 +0100 Subject: [PATCH 07/80] Prevent deletion of already authenticated account --- app/Http/Controllers/AccountAuthController.php | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/AccountAuthController.php b/app/Http/Controllers/AccountAuthController.php index ed3355ef..0ab213b9 100644 --- a/app/Http/Controllers/AccountAuthController.php +++ b/app/Http/Controllers/AccountAuthController.php @@ -95,15 +95,19 @@ public function updateAccountType() { return redirect()->back()->withErrors('This account is already registered as '.Helper::formatAccountTypeName(request('account_type')).'!'); } } else { - return redirect(route('create-account'))->withErrors(['You should register a Old School RuneScape account first!']); + return redirect(route('create-account'))->withErrors(['This account does not have a pending status anymore!']); } } public function delete() { $authStatus = AccountAuthStatus::where('user_id', Auth::user()->id)->where('status', '!=', 'success')->first(); - $authStatus->delete(); + if ($authStatus) { + $authStatus->delete(); - return redirect(route('create-account'))->with('message', 'Account authentication status deleted!'); + return redirect(route('create-account'))->with('message', 'Account authentication status deleted!'); + } else { + return redirect(route('create-account'))->withErrors(['This account does not have a pending status anymore!']); + } } } From 7699c4b2799632db29f6cab3cad7d97f8c13f64b Mon Sep 17 00:00:00 2001 From: Simon Date: Sat, 31 Oct 2020 00:55:04 +0100 Subject: [PATCH 08/80] Total and average kill counts & account hiscore Routing to account hiscore by username --- app/Http/Controllers/AccountController.php | 4 +- .../Controllers/Api/HiscoreController.php | 15 +- public/js/app.js | 1254 ++++++++++++++++- resources/js/app.js | 2 +- .../{Account.vue => AccountHiscore.vue} | 18 +- resources/js/components/BossHiscore.vue | 11 +- resources/js/components/SkillHiscore.vue | 2 +- resources/views/account/show.blade.php | 2 +- routes/web.php | 2 +- 9 files changed, 1227 insertions(+), 83 deletions(-) rename resources/js/components/{Account.vue => AccountHiscore.vue} (68%) diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 1abc02e3..401f4ad5 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -47,8 +47,8 @@ public function create() { * @param string $username * @return */ - public function show($account) { - $account = Account::findOrFail($account); + public function show($accountUsername) { + $account = Account::where('username', $accountUsername)->firstOrFail(); return view('account.show', compact('account')); } diff --git a/app/Http/Controllers/Api/HiscoreController.php b/app/Http/Controllers/Api/HiscoreController.php index 15014e4c..53742437 100644 --- a/app/Http/Controllers/Api/HiscoreController.php +++ b/app/Http/Controllers/Api/HiscoreController.php @@ -69,7 +69,7 @@ public function skill($skillName) { 'total_xp' => number_format($sumTotalXp), 'average_total_level' => round($averageTotalLevel), 'total_max_level' => $totalMaxLevel, - ]]); + ]]); } else { return response()->json("There are no linked accounts", 404); } @@ -81,9 +81,18 @@ public function boss($bossName) { $boss = $collection->model::with('account')->orderBy('kill_count', 'DESC')->get(); - $bosses = Helper::listBosses(); + $sumKills = $collection->model::selectRaw('SUM(kill_count) AS total_kill_count') + ->selectRaw('COUNT(*) AS total_kills') + ->first(); - return BossHiscoreResource::collection($boss); + $averageTotalKills = $sumKills["total_kill_count"] / $sumKills["total_kills"]; + + return BossHiscoreResource::collection($boss) + ->additional(['meta' => [ + 'boss' => ucfirst($bossName), + 'total_kills' => number_format($sumKills["total_kill_count"]), + 'average_total_kills' => round($averageTotalKills), + ]]); } else { return response()->json("There are no linked accounts", 404); } diff --git a/public/js/app.js b/public/js/app.js index 08fd3978..a5a73c73 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -1899,10 +1899,10 @@ module.exports = { /***/ }), -/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/Account.vue?vue&type=script&lang=js&": -/*!******************************************************************************************************************************************************************!*\ - !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/Account.vue?vue&type=script&lang=js& ***! - \******************************************************************************************************************************************************************/ +/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/AccountHiscore.vue?vue&type=script&lang=js&": +/*!*************************************************************************************************************************************************************************!*\ + !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/AccountHiscore.vue?vue&type=script&lang=js& ***! + \*************************************************************************************************************************************************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { @@ -1946,22 +1946,22 @@ __webpack_require__.r(__webpack_exports__); // /* harmony default export */ __webpack_exports__["default"] = ({ props: { - accountId: { - type: Number, + account: { + type: String, required: true } }, data: function data() { return { - account: {}, + data: {}, hiscores: {} }; }, mounted: function mounted() { var _this = this; - axios.get('/api/account/' + this.accountId).then(function (response) { - _this.account = response.data.data; + axios.get('/api/account/Vanskelig').then(function (response) { + _this.data = response.data.data; _this.hiscores = response.data.meta.hiscores; })["catch"](function (error) { return console.log(error); @@ -2006,6 +2006,13 @@ __webpack_require__.r(__webpack_exports__); // // // +// +// +// +// +// +// +// /* harmony default export */ __webpack_exports__["default"] = ({ props: { boss: { @@ -2015,7 +2022,8 @@ __webpack_require__.r(__webpack_exports__); }, data: function data() { return { - hiscores: {} + hiscores: {}, + meta: {} }; }, mounted: function mounted() { @@ -2023,6 +2031,7 @@ __webpack_require__.r(__webpack_exports__); axios.get('/api/hiscore/boss/' + this.boss).then(function (response) { _this.hiscores = response.data.data; + _this.meta = response.data.meta; })["catch"](function (error) { return console.log(error); }); @@ -2072,27 +2081,862 @@ __webpack_require__.r(__webpack_exports__); // // /* harmony default export */ __webpack_exports__["default"] = ({ - props: { - skill: { - type: String, - required: true - } - }, + props: { + skill: { + type: String, + required: true + } + }, + data: function data() { + return { + hiscores: {}, + meta: {} + }; + }, + mounted: function mounted() { + var _this = this; + + axios.get('/api/hiscore/skill/' + this.skill).then(function (response) { + _this.hiscores = response.data.data; + _this.meta = response.data.meta; + })["catch"](function (error) { + return console.log(error); + }); + } +}); + +/***/ }), + +/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/AuthorizedClients.vue?vue&type=script&lang=js&": +/*!*************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/passport/AuthorizedClients.vue?vue&type=script&lang=js& ***! + \*************************************************************************************************************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +/* harmony default export */ __webpack_exports__["default"] = ({ + /* + * The component's data. + */ + data: function data() { + return { + tokens: [] + }; + }, + + /** + * Prepare the component (Vue 1.x). + */ + ready: function ready() { + this.prepareComponent(); + }, + + /** + * Prepare the component (Vue 2.x). + */ + mounted: function mounted() { + this.prepareComponent(); + }, + methods: { + /** + * Prepare the component (Vue 2.x). + */ + prepareComponent: function prepareComponent() { + this.getTokens(); + }, + + /** + * Get all of the authorized tokens for the user. + */ + getTokens: function getTokens() { + var _this = this; + + axios.get('/oauth/tokens').then(function (response) { + _this.tokens = response.data; + }); + }, + + /** + * Revoke the given token. + */ + revoke: function revoke(token) { + var _this2 = this; + + axios["delete"]('/oauth/tokens/' + token.id).then(function (response) { + _this2.getTokens(); + }); + } + } +}); + +/***/ }), + +/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/Clients.vue?vue&type=script&lang=js&": +/*!***************************************************************************************************************************************************************************!*\ + !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/passport/Clients.vue?vue&type=script&lang=js& ***! + \***************************************************************************************************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +/* harmony default export */ __webpack_exports__["default"] = ({ + /* + * The component's data. + */ + data: function data() { + return { + clients: [], + clientSecret: null, + createForm: { + errors: [], + name: '', + redirect: '', + confidential: true + }, + editForm: { + errors: [], + name: '', + redirect: '' + } + }; + }, + + /** + * Prepare the component (Vue 1.x). + */ + ready: function ready() { + this.prepareComponent(); + }, + + /** + * Prepare the component (Vue 2.x). + */ + mounted: function mounted() { + this.prepareComponent(); + }, + methods: { + /** + * Prepare the component. + */ + prepareComponent: function prepareComponent() { + this.getClients(); + $('#modal-create-client').on('shown.bs.modal', function () { + $('#create-client-name').focus(); + }); + $('#modal-edit-client').on('shown.bs.modal', function () { + $('#edit-client-name').focus(); + }); + }, + + /** + * Get all of the OAuth clients for the user. + */ + getClients: function getClients() { + var _this = this; + + axios.get('/oauth/clients').then(function (response) { + _this.clients = response.data; + }); + }, + + /** + * Show the form for creating new clients. + */ + showCreateClientForm: function showCreateClientForm() { + $('#modal-create-client').modal('show'); + }, + + /** + * Create a new OAuth client for the user. + */ + store: function store() { + this.persistClient('post', '/oauth/clients', this.createForm, '#modal-create-client'); + }, + + /** + * Edit the given client. + */ + edit: function edit(client) { + this.editForm.id = client.id; + this.editForm.name = client.name; + this.editForm.redirect = client.redirect; + $('#modal-edit-client').modal('show'); + }, + + /** + * Update the client being edited. + */ + update: function update() { + this.persistClient('put', '/oauth/clients/' + this.editForm.id, this.editForm, '#modal-edit-client'); + }, + + /** + * Persist the client to storage using the given form. + */ + persistClient: function persistClient(method, uri, form, modal) { + var _this2 = this; + + form.errors = []; + axios[method](uri, form).then(function (response) { + _this2.getClients(); + + form.name = ''; + form.redirect = ''; + form.errors = []; + $(modal).modal('hide'); + + if (response.data.plainSecret) { + _this2.showClientSecret(response.data.plainSecret); + } + })["catch"](function (error) { + if (_typeof(error.response.data) === 'object') { + form.errors = _.flatten(_.toArray(error.response.data.errors)); + } else { + form.errors = ['Something went wrong. Please try again.']; + } + }); + }, + + /** + * Show the given client secret to the user. + */ + showClientSecret: function showClientSecret(clientSecret) { + this.clientSecret = clientSecret; + $('#modal-client-secret').modal('show'); + }, + + /** + * Destroy the given client. + */ + destroy: function destroy(client) { + var _this3 = this; + + axios["delete"]('/oauth/clients/' + client.id).then(function (response) { + _this3.getClients(); + }); + } + } +}); + +/***/ }), + +/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=script&lang=js&": +/*!****************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=script&lang=js& ***! + \****************************************************************************************************************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } + +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +/* harmony default export */ __webpack_exports__["default"] = ({ + /* + * The component's data. + */ data: function data() { return { - hiscores: {}, - meta: {} + accessToken: null, + tokens: [], + scopes: [], + form: { + name: '', + scopes: [], + errors: [] + } }; }, + + /** + * Prepare the component (Vue 1.x). + */ + ready: function ready() { + this.prepareComponent(); + }, + + /** + * Prepare the component (Vue 2.x). + */ mounted: function mounted() { - var _this = this; + this.prepareComponent(); + }, + methods: { + /** + * Prepare the component. + */ + prepareComponent: function prepareComponent() { + this.getTokens(); + this.getScopes(); + $('#modal-create-token').on('shown.bs.modal', function () { + $('#create-token-name').focus(); + }); + }, - axios.get('/api/hiscore/skill/' + this.skill).then(function (response) { - _this.hiscores = response.data.data; - _this.meta = response.data.meta; - })["catch"](function (error) { - return console.log(error); - }); + /** + * Get all of the personal access tokens for the user. + */ + getTokens: function getTokens() { + var _this = this; + + axios.get('/oauth/personal-access-tokens').then(function (response) { + _this.tokens = response.data; + }); + }, + + /** + * Get all of the available scopes. + */ + getScopes: function getScopes() { + var _this2 = this; + + axios.get('/oauth/scopes').then(function (response) { + _this2.scopes = response.data; + }); + }, + + /** + * Show the form for creating new tokens. + */ + showCreateTokenForm: function showCreateTokenForm() { + $('#modal-create-token').modal('show'); + }, + + /** + * Create a new personal access token. + */ + store: function store() { + var _this3 = this; + + this.accessToken = null; + this.form.errors = []; + axios.post('/oauth/personal-access-tokens', this.form).then(function (response) { + _this3.form.name = ''; + _this3.form.scopes = []; + _this3.form.errors = []; + + _this3.tokens.push(response.data.token); + + _this3.showAccessToken(response.data.accessToken); + })["catch"](function (error) { + if (_typeof(error.response.data) === 'object') { + _this3.form.errors = _.flatten(_.toArray(error.response.data.errors)); + } else { + _this3.form.errors = ['Something went wrong. Please try again.']; + } + }); + }, + + /** + * Toggle the given scope in the list of assigned scopes. + */ + toggleScope: function toggleScope(scope) { + if (this.scopeIsAssigned(scope)) { + this.form.scopes = _.reject(this.form.scopes, function (s) { + return s == scope; + }); + } else { + this.form.scopes.push(scope); + } + }, + + /** + * Determine if the given scope has been assigned to the token. + */ + scopeIsAssigned: function scopeIsAssigned(scope) { + return _.indexOf(this.form.scopes, scope) >= 0; + }, + + /** + * Show the given access token to the user. + */ + showAccessToken: function showAccessToken(accessToken) { + $('#modal-create-token').modal('hide'); + this.accessToken = accessToken; + $('#modal-access-token').modal('show'); + }, + + /** + * Revoke the given token. + */ + revoke: function revoke(token) { + var _this4 = this; + + axios["delete"]('/oauth/personal-access-tokens/' + token.id).then(function (response) { + _this4.getTokens(); + }); + } } }); @@ -38418,10 +39262,10 @@ exports.clearImmediate = (typeof self !== "undefined" && self.clearImmediate) || /***/ }), -/***/ "./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/Account.vue?vue&type=template&id=0b1dd512&": -/*!**********************************************************************************************************************************************************************************************************!*\ - !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/Account.vue?vue&type=template&id=0b1dd512& ***! - \**********************************************************************************************************************************************************************************************************/ +/***/ "./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/AccountHiscore.vue?vue&type=template&id=6cb7f722&": +/*!*****************************************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/AccountHiscore.vue?vue&type=template&id=6cb7f722& ***! + \*****************************************************************************************************************************************************************************************************************/ /*! exports provided: render, staticRenderFns */ /***/ (function(module, __webpack_exports__, __webpack_require__) { @@ -38436,33 +39280,33 @@ var render = function() { return _c("div", [ _c("div", { staticClass: "float-left ml-3" }, [ _c("h1", { staticClass: "text-left" }, [ - _vm._v(_vm._s(_vm.account.username)) + _vm._v(_vm._s(_vm.data.username)) ]), _vm._v(" "), _c("span", [ _vm._v("Rank: "), - _c("strong", [_vm._v(_vm._s(_vm.account.rank))]) + _c("strong", [_vm._v(_vm._s(_vm.data.rank))]) ]), _vm._v(" "), _c("br"), _vm._v(" "), _c("span", [ _vm._v("Total XP: "), - _c("strong", [_vm._v(_vm._s(_vm.account.xp))]) + _c("strong", [_vm._v(_vm._s(_vm.data.xp))]) ]), _vm._v(" "), _c("br"), _vm._v(" "), _c("span", [ _vm._v("Total Level: "), - _c("strong", [_vm._v(_vm._s(_vm.account.level))]) + _c("strong", [_vm._v(_vm._s(_vm.data.level))]) ]), _vm._v(" "), _c("br"), _vm._v(" "), _c("span", [ _vm._v("Joined: "), - _c("strong", [_vm._v(_vm._s(_vm.account.joined))]) + _c("strong", [_vm._v(_vm._s(_vm.data.joined))]) ]) ]), _vm._v(" "), @@ -38541,6 +39385,22 @@ var render = function() { var _h = _vm.$createElement var _c = _vm._self._c || _h return _c("div", [ + _c("div", { staticClass: "float-left mt-3 ml-3" }, [ + _c("h1", { staticClass: "text-left" }, [_vm._v(_vm._s(_vm.meta.boss))]), + _vm._v(" "), + _c("span", [ + _vm._v("Total Kills: "), + _c("strong", [_vm._v(_vm._s(_vm.meta.total_kills))]) + ]), + _vm._v(" "), + _c("br"), + _vm._v(" "), + _c("span", [ + _vm._v("Average Kills: "), + _c("strong", [_vm._v(_vm._s(_vm.meta.average_total_kills))]) + ]) + ]), + _vm._v(" "), _c( "table", [ @@ -38551,9 +39411,11 @@ var render = function() { _c("td", [_vm._v(_vm._s(index + 1))]), _vm._v(" "), _c("td", [ - _c("a", { attrs: { href: "/account/" + hiscore.account.id } }, [ - _vm._v(_vm._s(hiscore.account.username)) - ]) + _c( + "a", + { attrs: { href: "/account/" + hiscore.account.username } }, + [_vm._v(_vm._s(hiscore.account.username))] + ) ]), _vm._v(" "), _c("td", [_vm._v(_vm._s(hiscore.kill_count))]), @@ -38637,7 +39499,7 @@ var render = function() { _c("td", [_vm._v(_vm._s(index + 1))]), _vm._v(" "), _c("td", [ - _c("a", { attrs: { href: "/account/" + hiscore.id } }, [ + _c("a", { attrs: { href: "/account/" + hiscore.username } }, [ _vm._v(_vm._s(hiscore.username)) ]) ]), @@ -52118,7 +52980,10 @@ window.Vue = __webpack_require__(/*! vue */ "./node_modules/vue/dist/vue.common. Vue.component('skillhiscore', __webpack_require__(/*! ./components/SkillHiscore.vue */ "./resources/js/components/SkillHiscore.vue")["default"]); Vue.component('bosshiscore', __webpack_require__(/*! ./components/BossHiscore.vue */ "./resources/js/components/BossHiscore.vue")["default"]); -Vue.component('account', __webpack_require__(/*! ./components/Account.vue */ "./resources/js/components/Account.vue")["default"]); +Vue.component('accounthiscore', __webpack_require__(/*! ./components/AccountHiscore.vue */ "./resources/js/components/AccountHiscore.vue")["default"]); +Vue.component('passport-clients', __webpack_require__(/*! ./components/passport/Clients.vue */ "./resources/js/components/passport/Clients.vue")["default"]); +Vue.component('passport-authorized-clients', __webpack_require__(/*! ./components/passport/AuthorizedClients.vue */ "./resources/js/components/passport/AuthorizedClients.vue")["default"]); +Vue.component('passport-personal-access-tokens', __webpack_require__(/*! ./components/passport/PersonalAccessTokens.vue */ "./resources/js/components/passport/PersonalAccessTokens.vue")["default"]); /** * Next, we will create a fresh Vue application instance and attach it to * the page. Then, you may begin adding components to this application @@ -52176,17 +53041,17 @@ window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; /***/ }), -/***/ "./resources/js/components/Account.vue": -/*!*********************************************!*\ - !*** ./resources/js/components/Account.vue ***! - \*********************************************/ +/***/ "./resources/js/components/AccountHiscore.vue": +/*!****************************************************!*\ + !*** ./resources/js/components/AccountHiscore.vue ***! + \****************************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _Account_vue_vue_type_template_id_0b1dd512___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Account.vue?vue&type=template&id=0b1dd512& */ "./resources/js/components/Account.vue?vue&type=template&id=0b1dd512&"); -/* harmony import */ var _Account_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Account.vue?vue&type=script&lang=js& */ "./resources/js/components/Account.vue?vue&type=script&lang=js&"); +/* harmony import */ var _AccountHiscore_vue_vue_type_template_id_6cb7f722___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AccountHiscore.vue?vue&type=template&id=6cb7f722& */ "./resources/js/components/AccountHiscore.vue?vue&type=template&id=6cb7f722&"); +/* harmony import */ var _AccountHiscore_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./AccountHiscore.vue?vue&type=script&lang=js& */ "./resources/js/components/AccountHiscore.vue?vue&type=script&lang=js&"); /* empty/unused harmony star reexport *//* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ "./node_modules/vue-loader/lib/runtime/componentNormalizer.js"); @@ -52196,9 +53061,9 @@ __webpack_require__.r(__webpack_exports__); /* normalize component */ var component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_2__["default"])( - _Account_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__["default"], - _Account_vue_vue_type_template_id_0b1dd512___WEBPACK_IMPORTED_MODULE_0__["render"], - _Account_vue_vue_type_template_id_0b1dd512___WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"], + _AccountHiscore_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__["default"], + _AccountHiscore_vue_vue_type_template_id_6cb7f722___WEBPACK_IMPORTED_MODULE_0__["render"], + _AccountHiscore_vue_vue_type_template_id_6cb7f722___WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"], false, null, null, @@ -52208,38 +53073,38 @@ var component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_ /* hot reload */ if (false) { var api; } -component.options.__file = "resources/js/components/Account.vue" +component.options.__file = "resources/js/components/AccountHiscore.vue" /* harmony default export */ __webpack_exports__["default"] = (component.exports); /***/ }), -/***/ "./resources/js/components/Account.vue?vue&type=script&lang=js&": -/*!**********************************************************************!*\ - !*** ./resources/js/components/Account.vue?vue&type=script&lang=js& ***! - \**********************************************************************/ +/***/ "./resources/js/components/AccountHiscore.vue?vue&type=script&lang=js&": +/*!*****************************************************************************!*\ + !*** ./resources/js/components/AccountHiscore.vue?vue&type=script&lang=js& ***! + \*****************************************************************************/ /*! exports provided: default */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _node_modules_babel_loader_lib_index_js_ref_4_0_node_modules_vue_loader_lib_index_js_vue_loader_options_Account_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib??ref--4-0!../../../node_modules/vue-loader/lib??vue-loader-options!./Account.vue?vue&type=script&lang=js& */ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/Account.vue?vue&type=script&lang=js&"); -/* empty/unused harmony star reexport */ /* harmony default export */ __webpack_exports__["default"] = (_node_modules_babel_loader_lib_index_js_ref_4_0_node_modules_vue_loader_lib_index_js_vue_loader_options_Account_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__["default"]); +/* harmony import */ var _node_modules_babel_loader_lib_index_js_ref_4_0_node_modules_vue_loader_lib_index_js_vue_loader_options_AccountHiscore_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/babel-loader/lib??ref--4-0!../../../node_modules/vue-loader/lib??vue-loader-options!./AccountHiscore.vue?vue&type=script&lang=js& */ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/AccountHiscore.vue?vue&type=script&lang=js&"); +/* empty/unused harmony star reexport */ /* harmony default export */ __webpack_exports__["default"] = (_node_modules_babel_loader_lib_index_js_ref_4_0_node_modules_vue_loader_lib_index_js_vue_loader_options_AccountHiscore_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__["default"]); /***/ }), -/***/ "./resources/js/components/Account.vue?vue&type=template&id=0b1dd512&": -/*!****************************************************************************!*\ - !*** ./resources/js/components/Account.vue?vue&type=template&id=0b1dd512& ***! - \****************************************************************************/ +/***/ "./resources/js/components/AccountHiscore.vue?vue&type=template&id=6cb7f722&": +/*!***********************************************************************************!*\ + !*** ./resources/js/components/AccountHiscore.vue?vue&type=template&id=6cb7f722& ***! + \***********************************************************************************/ /*! exports provided: render, staticRenderFns */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); -/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_Account_vue_vue_type_template_id_0b1dd512___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../node_modules/vue-loader/lib??vue-loader-options!./Account.vue?vue&type=template&id=0b1dd512& */ "./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/Account.vue?vue&type=template&id=0b1dd512&"); -/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "render", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_Account_vue_vue_type_template_id_0b1dd512___WEBPACK_IMPORTED_MODULE_0__["render"]; }); +/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_AccountHiscore_vue_vue_type_template_id_6cb7f722___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../node_modules/vue-loader/lib??vue-loader-options!./AccountHiscore.vue?vue&type=template&id=6cb7f722& */ "./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/AccountHiscore.vue?vue&type=template&id=6cb7f722&"); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "render", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_AccountHiscore_vue_vue_type_template_id_6cb7f722___WEBPACK_IMPORTED_MODULE_0__["render"]; }); -/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "staticRenderFns", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_Account_vue_vue_type_template_id_0b1dd512___WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"]; }); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "staticRenderFns", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_AccountHiscore_vue_vue_type_template_id_6cb7f722___WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"]; }); @@ -52381,6 +53246,267 @@ __webpack_require__.r(__webpack_exports__); +/***/ }), + +/***/ "./resources/js/components/passport/AuthorizedClients.vue": +/*!****************************************************************!*\ + !*** ./resources/js/components/passport/AuthorizedClients.vue ***! + \****************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _AuthorizedClients_vue_vue_type_template_id_397d14ca_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./AuthorizedClients.vue?vue&type=template&id=397d14ca&scoped=true& */ "./resources/js/components/passport/AuthorizedClients.vue?vue&type=template&id=397d14ca&scoped=true&"); +/* harmony import */ var _AuthorizedClients_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./AuthorizedClients.vue?vue&type=script&lang=js& */ "./resources/js/components/passport/AuthorizedClients.vue?vue&type=script&lang=js&"); +/* empty/unused harmony star reexport *//* harmony import */ var _AuthorizedClients_vue_vue_type_style_index_0_id_397d14ca_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./AuthorizedClients.vue?vue&type=style&index=0&id=397d14ca&scoped=true&lang=css& */ "./resources/js/components/passport/AuthorizedClients.vue?vue&type=style&index=0&id=397d14ca&scoped=true&lang=css&"); +/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ "./node_modules/vue-loader/lib/runtime/componentNormalizer.js"); + + + + + + +/* normalize component */ + +var component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__["default"])( + _AuthorizedClients_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__["default"], + _AuthorizedClients_vue_vue_type_template_id_397d14ca_scoped_true___WEBPACK_IMPORTED_MODULE_0__["render"], + _AuthorizedClients_vue_vue_type_template_id_397d14ca_scoped_true___WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"], + false, + null, + "397d14ca", + null + +) + +/* hot reload */ +if (false) { var api; } +component.options.__file = "resources/js/components/passport/AuthorizedClients.vue" +/* harmony default export */ __webpack_exports__["default"] = (component.exports); + +/***/ }), + +/***/ "./resources/js/components/passport/AuthorizedClients.vue?vue&type=script&lang=js&": +/*!*****************************************************************************************!*\ + !*** ./resources/js/components/passport/AuthorizedClients.vue?vue&type=script&lang=js& ***! + \*****************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _node_modules_babel_loader_lib_index_js_ref_4_0_node_modules_vue_loader_lib_index_js_vue_loader_options_AuthorizedClients_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/babel-loader/lib??ref--4-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./AuthorizedClients.vue?vue&type=script&lang=js& */ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/AuthorizedClients.vue?vue&type=script&lang=js&"); +/* empty/unused harmony star reexport */ /* harmony default export */ __webpack_exports__["default"] = (_node_modules_babel_loader_lib_index_js_ref_4_0_node_modules_vue_loader_lib_index_js_vue_loader_options_AuthorizedClients_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__["default"]); + +/***/ }), + +/***/ "./resources/js/components/passport/AuthorizedClients.vue?vue&type=style&index=0&id=397d14ca&scoped=true&lang=css&": +/*!*************************************************************************************************************************!*\ + !*** ./resources/js/components/passport/AuthorizedClients.vue?vue&type=style&index=0&id=397d14ca&scoped=true&lang=css& ***! + \*************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _node_modules_style_loader_index_js_node_modules_css_loader_index_js_ref_6_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_2_node_modules_vue_loader_lib_index_js_vue_loader_options_AuthorizedClients_vue_vue_type_style_index_0_id_397d14ca_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/style-loader!../../../../node_modules/css-loader??ref--6-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/postcss-loader/src??ref--6-2!../../../../node_modules/vue-loader/lib??vue-loader-options!./AuthorizedClients.vue?vue&type=style&index=0&id=397d14ca&scoped=true&lang=css& */ "./node_modules/style-loader/index.js!./node_modules/css-loader/index.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/AuthorizedClients.vue?vue&type=style&index=0&id=397d14ca&scoped=true&lang=css&"); +/* harmony import */ var _node_modules_style_loader_index_js_node_modules_css_loader_index_js_ref_6_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_2_node_modules_vue_loader_lib_index_js_vue_loader_options_AuthorizedClients_vue_vue_type_style_index_0_id_397d14ca_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_index_js_node_modules_css_loader_index_js_ref_6_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_2_node_modules_vue_loader_lib_index_js_vue_loader_options_AuthorizedClients_vue_vue_type_style_index_0_id_397d14ca_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__); +/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_style_loader_index_js_node_modules_css_loader_index_js_ref_6_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_2_node_modules_vue_loader_lib_index_js_vue_loader_options_AuthorizedClients_vue_vue_type_style_index_0_id_397d14ca_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__) if(__WEBPACK_IMPORT_KEY__ !== 'default') (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_style_loader_index_js_node_modules_css_loader_index_js_ref_6_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_2_node_modules_vue_loader_lib_index_js_vue_loader_options_AuthorizedClients_vue_vue_type_style_index_0_id_397d14ca_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__)); + /* harmony default export */ __webpack_exports__["default"] = (_node_modules_style_loader_index_js_node_modules_css_loader_index_js_ref_6_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_2_node_modules_vue_loader_lib_index_js_vue_loader_options_AuthorizedClients_vue_vue_type_style_index_0_id_397d14ca_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default.a); + +/***/ }), + +/***/ "./resources/js/components/passport/AuthorizedClients.vue?vue&type=template&id=397d14ca&scoped=true&": +/*!***********************************************************************************************************!*\ + !*** ./resources/js/components/passport/AuthorizedClients.vue?vue&type=template&id=397d14ca&scoped=true& ***! + \***********************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_AuthorizedClients_vue_vue_type_template_id_397d14ca_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../../node_modules/vue-loader/lib??vue-loader-options!./AuthorizedClients.vue?vue&type=template&id=397d14ca&scoped=true& */ "./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/AuthorizedClients.vue?vue&type=template&id=397d14ca&scoped=true&"); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "render", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_AuthorizedClients_vue_vue_type_template_id_397d14ca_scoped_true___WEBPACK_IMPORTED_MODULE_0__["render"]; }); + +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "staticRenderFns", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_AuthorizedClients_vue_vue_type_template_id_397d14ca_scoped_true___WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"]; }); + + + +/***/ }), + +/***/ "./resources/js/components/passport/Clients.vue": +/*!******************************************************!*\ + !*** ./resources/js/components/passport/Clients.vue ***! + \******************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _Clients_vue_vue_type_template_id_1552a5b6_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Clients.vue?vue&type=template&id=1552a5b6&scoped=true& */ "./resources/js/components/passport/Clients.vue?vue&type=template&id=1552a5b6&scoped=true&"); +/* harmony import */ var _Clients_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Clients.vue?vue&type=script&lang=js& */ "./resources/js/components/passport/Clients.vue?vue&type=script&lang=js&"); +/* empty/unused harmony star reexport *//* harmony import */ var _Clients_vue_vue_type_style_index_0_id_1552a5b6_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Clients.vue?vue&type=style&index=0&id=1552a5b6&scoped=true&lang=css& */ "./resources/js/components/passport/Clients.vue?vue&type=style&index=0&id=1552a5b6&scoped=true&lang=css&"); +/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ "./node_modules/vue-loader/lib/runtime/componentNormalizer.js"); + + + + + + +/* normalize component */ + +var component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__["default"])( + _Clients_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__["default"], + _Clients_vue_vue_type_template_id_1552a5b6_scoped_true___WEBPACK_IMPORTED_MODULE_0__["render"], + _Clients_vue_vue_type_template_id_1552a5b6_scoped_true___WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"], + false, + null, + "1552a5b6", + null + +) + +/* hot reload */ +if (false) { var api; } +component.options.__file = "resources/js/components/passport/Clients.vue" +/* harmony default export */ __webpack_exports__["default"] = (component.exports); + +/***/ }), + +/***/ "./resources/js/components/passport/Clients.vue?vue&type=script&lang=js&": +/*!*******************************************************************************!*\ + !*** ./resources/js/components/passport/Clients.vue?vue&type=script&lang=js& ***! + \*******************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _node_modules_babel_loader_lib_index_js_ref_4_0_node_modules_vue_loader_lib_index_js_vue_loader_options_Clients_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/babel-loader/lib??ref--4-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./Clients.vue?vue&type=script&lang=js& */ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/Clients.vue?vue&type=script&lang=js&"); +/* empty/unused harmony star reexport */ /* harmony default export */ __webpack_exports__["default"] = (_node_modules_babel_loader_lib_index_js_ref_4_0_node_modules_vue_loader_lib_index_js_vue_loader_options_Clients_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__["default"]); + +/***/ }), + +/***/ "./resources/js/components/passport/Clients.vue?vue&type=style&index=0&id=1552a5b6&scoped=true&lang=css&": +/*!***************************************************************************************************************!*\ + !*** ./resources/js/components/passport/Clients.vue?vue&type=style&index=0&id=1552a5b6&scoped=true&lang=css& ***! + \***************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _node_modules_style_loader_index_js_node_modules_css_loader_index_js_ref_6_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_2_node_modules_vue_loader_lib_index_js_vue_loader_options_Clients_vue_vue_type_style_index_0_id_1552a5b6_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/style-loader!../../../../node_modules/css-loader??ref--6-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/postcss-loader/src??ref--6-2!../../../../node_modules/vue-loader/lib??vue-loader-options!./Clients.vue?vue&type=style&index=0&id=1552a5b6&scoped=true&lang=css& */ "./node_modules/style-loader/index.js!./node_modules/css-loader/index.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/Clients.vue?vue&type=style&index=0&id=1552a5b6&scoped=true&lang=css&"); +/* harmony import */ var _node_modules_style_loader_index_js_node_modules_css_loader_index_js_ref_6_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_2_node_modules_vue_loader_lib_index_js_vue_loader_options_Clients_vue_vue_type_style_index_0_id_1552a5b6_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_index_js_node_modules_css_loader_index_js_ref_6_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_2_node_modules_vue_loader_lib_index_js_vue_loader_options_Clients_vue_vue_type_style_index_0_id_1552a5b6_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__); +/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_style_loader_index_js_node_modules_css_loader_index_js_ref_6_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_2_node_modules_vue_loader_lib_index_js_vue_loader_options_Clients_vue_vue_type_style_index_0_id_1552a5b6_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__) if(__WEBPACK_IMPORT_KEY__ !== 'default') (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_style_loader_index_js_node_modules_css_loader_index_js_ref_6_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_2_node_modules_vue_loader_lib_index_js_vue_loader_options_Clients_vue_vue_type_style_index_0_id_1552a5b6_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__)); + /* harmony default export */ __webpack_exports__["default"] = (_node_modules_style_loader_index_js_node_modules_css_loader_index_js_ref_6_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_2_node_modules_vue_loader_lib_index_js_vue_loader_options_Clients_vue_vue_type_style_index_0_id_1552a5b6_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default.a); + +/***/ }), + +/***/ "./resources/js/components/passport/Clients.vue?vue&type=template&id=1552a5b6&scoped=true&": +/*!*************************************************************************************************!*\ + !*** ./resources/js/components/passport/Clients.vue?vue&type=template&id=1552a5b6&scoped=true& ***! + \*************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_Clients_vue_vue_type_template_id_1552a5b6_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../../node_modules/vue-loader/lib??vue-loader-options!./Clients.vue?vue&type=template&id=1552a5b6&scoped=true& */ "./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/Clients.vue?vue&type=template&id=1552a5b6&scoped=true&"); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "render", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_Clients_vue_vue_type_template_id_1552a5b6_scoped_true___WEBPACK_IMPORTED_MODULE_0__["render"]; }); + +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "staticRenderFns", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_Clients_vue_vue_type_template_id_1552a5b6_scoped_true___WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"]; }); + + + +/***/ }), + +/***/ "./resources/js/components/passport/PersonalAccessTokens.vue": +/*!*******************************************************************!*\ + !*** ./resources/js/components/passport/PersonalAccessTokens.vue ***! + \*******************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _PersonalAccessTokens_vue_vue_type_template_id_49962cc0_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./PersonalAccessTokens.vue?vue&type=template&id=49962cc0&scoped=true& */ "./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=template&id=49962cc0&scoped=true&"); +/* harmony import */ var _PersonalAccessTokens_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./PersonalAccessTokens.vue?vue&type=script&lang=js& */ "./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=script&lang=js&"); +/* empty/unused harmony star reexport *//* harmony import */ var _PersonalAccessTokens_vue_vue_type_style_index_0_id_49962cc0_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./PersonalAccessTokens.vue?vue&type=style&index=0&id=49962cc0&scoped=true&lang=css& */ "./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=style&index=0&id=49962cc0&scoped=true&lang=css&"); +/* harmony import */ var _node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js */ "./node_modules/vue-loader/lib/runtime/componentNormalizer.js"); + + + + + + +/* normalize component */ + +var component = Object(_node_modules_vue_loader_lib_runtime_componentNormalizer_js__WEBPACK_IMPORTED_MODULE_3__["default"])( + _PersonalAccessTokens_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_1__["default"], + _PersonalAccessTokens_vue_vue_type_template_id_49962cc0_scoped_true___WEBPACK_IMPORTED_MODULE_0__["render"], + _PersonalAccessTokens_vue_vue_type_template_id_49962cc0_scoped_true___WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"], + false, + null, + "49962cc0", + null + +) + +/* hot reload */ +if (false) { var api; } +component.options.__file = "resources/js/components/passport/PersonalAccessTokens.vue" +/* harmony default export */ __webpack_exports__["default"] = (component.exports); + +/***/ }), + +/***/ "./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=script&lang=js&": +/*!********************************************************************************************!*\ + !*** ./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=script&lang=js& ***! + \********************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _node_modules_babel_loader_lib_index_js_ref_4_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PersonalAccessTokens_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/babel-loader/lib??ref--4-0!../../../../node_modules/vue-loader/lib??vue-loader-options!./PersonalAccessTokens.vue?vue&type=script&lang=js& */ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=script&lang=js&"); +/* empty/unused harmony star reexport */ /* harmony default export */ __webpack_exports__["default"] = (_node_modules_babel_loader_lib_index_js_ref_4_0_node_modules_vue_loader_lib_index_js_vue_loader_options_PersonalAccessTokens_vue_vue_type_script_lang_js___WEBPACK_IMPORTED_MODULE_0__["default"]); + +/***/ }), + +/***/ "./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=style&index=0&id=49962cc0&scoped=true&lang=css&": +/*!****************************************************************************************************************************!*\ + !*** ./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=style&index=0&id=49962cc0&scoped=true&lang=css& ***! + \****************************************************************************************************************************/ +/*! no static exports found */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _node_modules_style_loader_index_js_node_modules_css_loader_index_js_ref_6_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_2_node_modules_vue_loader_lib_index_js_vue_loader_options_PersonalAccessTokens_vue_vue_type_style_index_0_id_49962cc0_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/style-loader!../../../../node_modules/css-loader??ref--6-1!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/postcss-loader/src??ref--6-2!../../../../node_modules/vue-loader/lib??vue-loader-options!./PersonalAccessTokens.vue?vue&type=style&index=0&id=49962cc0&scoped=true&lang=css& */ "./node_modules/style-loader/index.js!./node_modules/css-loader/index.js?!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/postcss-loader/src/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=style&index=0&id=49962cc0&scoped=true&lang=css&"); +/* harmony import */ var _node_modules_style_loader_index_js_node_modules_css_loader_index_js_ref_6_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_2_node_modules_vue_loader_lib_index_js_vue_loader_options_PersonalAccessTokens_vue_vue_type_style_index_0_id_49962cc0_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_style_loader_index_js_node_modules_css_loader_index_js_ref_6_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_2_node_modules_vue_loader_lib_index_js_vue_loader_options_PersonalAccessTokens_vue_vue_type_style_index_0_id_49962cc0_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__); +/* harmony reexport (unknown) */ for(var __WEBPACK_IMPORT_KEY__ in _node_modules_style_loader_index_js_node_modules_css_loader_index_js_ref_6_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_2_node_modules_vue_loader_lib_index_js_vue_loader_options_PersonalAccessTokens_vue_vue_type_style_index_0_id_49962cc0_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__) if(__WEBPACK_IMPORT_KEY__ !== 'default') (function(key) { __webpack_require__.d(__webpack_exports__, key, function() { return _node_modules_style_loader_index_js_node_modules_css_loader_index_js_ref_6_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_2_node_modules_vue_loader_lib_index_js_vue_loader_options_PersonalAccessTokens_vue_vue_type_style_index_0_id_49962cc0_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0__[key]; }) }(__WEBPACK_IMPORT_KEY__)); + /* harmony default export */ __webpack_exports__["default"] = (_node_modules_style_loader_index_js_node_modules_css_loader_index_js_ref_6_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_6_2_node_modules_vue_loader_lib_index_js_vue_loader_options_PersonalAccessTokens_vue_vue_type_style_index_0_id_49962cc0_scoped_true_lang_css___WEBPACK_IMPORTED_MODULE_0___default.a); + +/***/ }), + +/***/ "./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=template&id=49962cc0&scoped=true&": +/*!**************************************************************************************************************!*\ + !*** ./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=template&id=49962cc0&scoped=true& ***! + \**************************************************************************************************************/ +/*! exports provided: render, staticRenderFns */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_PersonalAccessTokens_vue_vue_type_template_id_49962cc0_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!../../../../node_modules/vue-loader/lib??vue-loader-options!./PersonalAccessTokens.vue?vue&type=template&id=49962cc0&scoped=true& */ "./node_modules/vue-loader/lib/loaders/templateLoader.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/passport/PersonalAccessTokens.vue?vue&type=template&id=49962cc0&scoped=true&"); +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "render", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_PersonalAccessTokens_vue_vue_type_template_id_49962cc0_scoped_true___WEBPACK_IMPORTED_MODULE_0__["render"]; }); + +/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "staticRenderFns", function() { return _node_modules_vue_loader_lib_loaders_templateLoader_js_vue_loader_options_node_modules_vue_loader_lib_index_js_vue_loader_options_PersonalAccessTokens_vue_vue_type_template_id_49962cc0_scoped_true___WEBPACK_IMPORTED_MODULE_0__["staticRenderFns"]; }); + + + /***/ }), /***/ "./resources/sass/app.scss": @@ -52401,8 +53527,8 @@ __webpack_require__.r(__webpack_exports__); /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { -__webpack_require__(/*! /home/simon/code/RuneManager-OSRS/resources/js/app.js */"./resources/js/app.js"); -module.exports = __webpack_require__(/*! /home/simon/code/RuneManager-OSRS/resources/sass/app.scss */"./resources/sass/app.scss"); +__webpack_require__(/*! C:\laragon\www\RuneManager-OSRS\resources\js\app.js */"./resources/js/app.js"); +module.exports = __webpack_require__(/*! C:\laragon\www\RuneManager-OSRS\resources\sass\app.scss */"./resources/sass/app.scss"); /***/ }) diff --git a/resources/js/app.js b/resources/js/app.js index 5edfd32b..14149a92 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -21,7 +21,7 @@ window.Vue = require('vue'); Vue.component('skillhiscore', require('./components/SkillHiscore.vue').default); Vue.component('bosshiscore', require('./components/BossHiscore.vue').default); -Vue.component('account', require('./components/Account.vue').default); +Vue.component('accounthiscore', require('./components/AccountHiscore.vue').default); Vue.component( 'passport-clients', diff --git a/resources/js/components/Account.vue b/resources/js/components/AccountHiscore.vue similarity index 68% rename from resources/js/components/Account.vue rename to resources/js/components/AccountHiscore.vue index 74a0051b..f34743a9 100644 --- a/resources/js/components/Account.vue +++ b/resources/js/components/AccountHiscore.vue @@ -1,15 +1,15 @@