diff --git a/etc/art/Graphictoria studio splash.psd b/etc/art/Graphictoria studio splash.psd index 56f6504..cf74611 100644 Binary files a/etc/art/Graphictoria studio splash.psd and b/etc/art/Graphictoria studio splash.psd differ diff --git a/web/app/Http/Controllers/BannerController.php b/web/app/Http/Controllers/BannerController.php index 002224e..a610bc4 100644 --- a/web/app/Http/Controllers/BannerController.php +++ b/web/app/Http/Controllers/BannerController.php @@ -37,8 +37,6 @@ class BannerController extends Controller } return response($content) - ->header('Access-Control-Allow-Origin', env('APP_URL')) - ->header('Vary', 'origin') ->header('Content-Type', 'application/json'); } } diff --git a/web/app/Http/Controllers/GamesController.php b/web/app/Http/Controllers/GamesController.php index fb5ab2f..18a8ec6 100644 --- a/web/app/Http/Controllers/GamesController.php +++ b/web/app/Http/Controllers/GamesController.php @@ -20,8 +20,6 @@ class GamesController extends Controller ->first(); return response()->json(['available' => $status->operational]) - ->header('Access-Control-Allow-Origin', env('APP_URL')) - ->header('Vary', 'origin') ->header('Content-Type', 'application/json'); } } diff --git a/web/app/Http/Kernel.php b/web/app/Http/Kernel.php index 39910d7..c3718e7 100644 --- a/web/app/Http/Kernel.php +++ b/web/app/Http/Kernel.php @@ -63,5 +63,6 @@ class Kernel extends HttpKernel 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, + 'cors' => \App\Http\Middleware\Cors::class, ]; } diff --git a/web/app/Http/Middleware/Cors.php b/web/app/Http/Middleware/Cors.php new file mode 100644 index 0000000..897ddd4 --- /dev/null +++ b/web/app/Http/Middleware/Cors.php @@ -0,0 +1,42 @@ +headers->get('origin'), PHP_URL_HOST); + + $passCheck = false; + + foreach($trustedHosts as &$host) + { + if(str_ends_with($origin, $host)) + $passCheck = true; + } + + $nextClosure = $next($request); + + if($passCheck) + { + $nextClosure + ->header('Access-Control-Allow-Origin', 'http' . ($request->secure() ? 's' : null) . '://' . $origin) + ->header('Vary', 'origin'); + } + + return $nextClosure; + } +} diff --git a/web/app/Providers/RouteServiceProvider.php b/web/app/Providers/RouteServiceProvider.php index e6f4c79..f0029e0 100644 --- a/web/app/Providers/RouteServiceProvider.php +++ b/web/app/Providers/RouteServiceProvider.php @@ -38,10 +38,10 @@ class RouteServiceProvider extends ServiceProvider $this->configureRateLimiting(); $this->routes(function () { - Route::domain('api.' . env('APP_URL')) + Route::domain('apis.' . env('APP_URL')) ->middleware('api') ->namespace($this->namespace) - ->group(base_path('routes/api.php')); + ->group(base_path('routes/apis.php')); Route::domain('www.' . env('APP_URL')) ->middleware('web') diff --git a/web/resources/js/helpers/Auth.js b/web/resources/js/helpers/Auth.js new file mode 100644 index 0000000..055d4b2 --- /dev/null +++ b/web/resources/js/helpers/Auth.js @@ -0,0 +1,9 @@ +// © XlXi 2021 +// Graphictoria 5 + +function CreateAccount(loginForm) +{ + +} + +export { CreateAccount }; \ No newline at end of file diff --git a/web/resources/js/layouts/App.js b/web/resources/js/layouts/App.js index c162443..e12e34b 100644 --- a/web/resources/js/layouts/App.js +++ b/web/resources/js/layouts/App.js @@ -37,7 +37,7 @@ class App extends React.Component { function updateBanners() { - axios.get(protocol + 'api.' + url + '/banners/data').then((response) => { + axios.get(protocol + 'apis.' + url + '/banners/data').then((response) => { var result = []; response.data.map(function(banner){ result.push(); diff --git a/web/resources/js/layouts/Card.js b/web/resources/js/layouts/Card.js new file mode 100644 index 0000000..54f6da9 --- /dev/null +++ b/web/resources/js/layouts/Card.js @@ -0,0 +1,30 @@ +// © XlXi 2021 +// Graphictoria 5 + +import React from 'react'; + +const Card = (props) => { + return ( +
+
+
+ { props.children } +
+
+
+ ); +}; + +const CardTitle = (props) => { + return ( + <> +
{ props.children }
+
+ + ); +}; + +export { + Card, + CardTitle +}; \ No newline at end of file diff --git a/web/resources/js/pages/Auth.js b/web/resources/js/pages/Auth.js index 30ddb7b..c5d6ddc 100644 --- a/web/resources/js/pages/Auth.js +++ b/web/resources/js/pages/Auth.js @@ -1,12 +1,19 @@ // © XlXi 2021 // Graphictoria 5 -import React from "react"; -import { Link } from "react-router-dom"; +import React from 'react'; +import { Link } from 'react-router-dom'; -import ReCAPTCHA from "react-google-recaptcha"; +import ReCAPTCHA from 'react-google-recaptcha'; -import SetTitle from "../Helpers/Title.js"; +import SetTitle from '../Helpers/Title.js'; +import { CreateAccount } from '../Helpers/Auth.js'; + +import { Card, CardTitle } from '../Layouts/Card.js'; + +import LoginForm from './Auth/Login.js'; +import ForgotPasswordForm from './Auth/ForgotPassword.js'; +import RegisterForm from './Auth/Register.js'; class Auth extends React.Component { componentDidMount() @@ -28,90 +35,29 @@ class Auth extends React.Component { { case '/login': pageLabel = (<> SIGN IN); - pageContent = ( - <> -
- - -
- -
-
- Forgot your password? -
-
-
New to Graphictoria?
-

Creating an account takes less than a minute, and you can join a community of 6k+ users for completely free.
Sign Up

-
- - ); + pageContent = (); break; case '/register': pageLabel = (<> REGISTER); pageContent = ( - <> -
-
-

Make sure your password is unique!

-
-
-
- -


- -

Make sure your email is valid, you'll need to confirm it.

- -


- -


-
- -
-
- Already have an account? -

By creating an account, you agree to our Terms of Service and our Privacy Policy.

-
- + ); break; case '/passwordreset': pageLabel = (<> RESET PASSWORD); - pageContent = ( -
- -
- -
-
- Login? -
- ); + pageContent = (); break; default: break; } return ( -
-
-
-
{ pageLabel }
-
-
- { pageContent } -
-
+ + { pageLabel } +
+ { pageContent }
-
+ ); } } diff --git a/web/resources/js/pages/Auth/ForgotPassword.js b/web/resources/js/pages/Auth/ForgotPassword.js new file mode 100644 index 0000000..18cd104 --- /dev/null +++ b/web/resources/js/pages/Auth/ForgotPassword.js @@ -0,0 +1,25 @@ +// © XlXi 2021 +// Graphictoria 5 + +import React from 'react'; +import { Link } from 'react-router-dom'; + +import ReCAPTCHA from 'react-google-recaptcha'; + +const ForgotPasswordForm = (props) => { + return ( +
+ +
+ +
+
+ Login? +
+ ); +}; + +export default ForgotPasswordForm; \ No newline at end of file diff --git a/web/resources/js/pages/Auth/Login.js b/web/resources/js/pages/Auth/Login.js new file mode 100644 index 0000000..f488ecf --- /dev/null +++ b/web/resources/js/pages/Auth/Login.js @@ -0,0 +1,32 @@ +// © XlXi 2021 +// Graphictoria 5 + +import React from 'react'; +import { Link } from 'react-router-dom'; + +import ReCAPTCHA from 'react-google-recaptcha'; + +const LoginForm = (props) => { + return ( + <> +
+ + +
+ +
+
+ Forgot your password? +
+
+
New to Graphictoria?
+

Creating an account takes less than a minute, and you can join a community of 6k+ users for completely free.
Sign Up

+
+ + ); +}; + +export default LoginForm; \ No newline at end of file diff --git a/web/resources/js/pages/Auth/Register.js b/web/resources/js/pages/Auth/Register.js new file mode 100644 index 0000000..6be0dc1 --- /dev/null +++ b/web/resources/js/pages/Auth/Register.js @@ -0,0 +1,107 @@ +// © XlXi 2021 +// Graphictoria 5 + +import React, { useState } from 'react'; +import { Link } from 'react-router-dom'; + +import ReCAPTCHA from 'react-google-recaptcha'; + +import Loader from '../../Components/Loader.js'; + +const RegisterForm = (props) => { + const RegistrationAreas = [ + { + text: 'Username', + type: 'username', + id: 'username' + }, + { + text: 'Email', + type: 'email', + id: 'email' + }, + { + text: 'Password', + type: 'password', + id: 'password' + }, + { + text: 'Confirm password', + type: 'password', + id: 'confirmation' + } + ]; + + const [waitingForSubmission, setWaitingForSubmission] = useState(false); + + const [values, setValues] = useState({ + username: '', + email: '', + password: '', + confirmation: '' + }); + + const [validity, setValidity] = useState({ + username: false, + email: false, + password: false, + confirmation: false + }); + + const [validityMessages, setValidityMessages] = useState({ + username: 'test', + email: '', + password: '', + confirmation: '' + }); + + const handleChange = (e) => { + const {id, value} = e.target; + + setValues(prevState => ({ + ...prevState, + [id] : value + })); + } + + function SubmitRegistration() + { + setWaitingForSubmission(true); + } + + return ( + waitingForSubmission + ? + + : + ( + <> +
+
+

Make sure your password is unique!

+
+
+
+ { + RegistrationAreas.map(({ text, type, id }, index) => + + ) + } +
+
+ +
+ +
+ Already have an account? +

By creating an account, you agree to our Terms of Service and our Privacy Policy.

+
+ + ) + ); +}; + +export default RegisterForm; \ No newline at end of file diff --git a/web/resources/js/pages/Errors.js b/web/resources/js/pages/Errors.js index fcdac3b..04c653a 100644 --- a/web/resources/js/pages/Errors.js +++ b/web/resources/js/pages/Errors.js @@ -6,37 +6,34 @@ import { Link, useHistory } from "react-router-dom"; import SetTitle from "../Helpers/Title.js"; +import { Card, CardTitle } from '../Layouts/Card.js'; + function GenericErrorModal(props) { const history = useHistory(); return ( -
-
-
-
{ props.title }
-
-

{ props.children }

- { - props.stack !== undefined && process.env.NODE_ENV === 'development' - ? -
- {/* this code is a jumbled mess */} - - STACK TRACE
{("-").repeat(15)}
{ props.stack } -
-
- : - null - } -
- Home - {/* eslint-disable-next-line */} - history.goBack() }>Back + + { props.title } +

{ props.children }

+ { + props.stack !== undefined && process.env.NODE_ENV === 'development' + ? +
+ {/* this code is a jumbled mess */} + + STACK TRACE
{("-").repeat(15)}
{ props.stack } +
-
+ : + null + } +
+ Home + {/* eslint-disable-next-line */} + history.goBack() }>Back
-
+ ); } diff --git a/web/resources/js/pages/Games.js b/web/resources/js/pages/Games.js index 41154ac..c95b540 100644 --- a/web/resources/js/pages/Games.js +++ b/web/resources/js/pages/Games.js @@ -31,7 +31,7 @@ class Games extends React.Component { SetTitle('Games'); - axios.get(protocol + 'api.' + url + '/games/metadata').then((response) => { + axios.get(protocol + 'apis.' + url + '/games/metadata').then((response) => { app.setState({loading: !(response.data.available == false), offline: !response.data.available}); }); } diff --git a/web/routes/api.php b/web/routes/apis.php similarity index 54% rename from web/routes/api.php rename to web/routes/apis.php index cdea6f0..d306f90 100644 --- a/web/routes/api.php +++ b/web/routes/apis.php @@ -16,16 +16,20 @@ use App\Http\Controllers\GamesController; | */ -Route::get('/', function () { - return 'API OK'; -}); +Route::middleware(['cors'])->group(function() { -Route::get('/banners/data', [BannerController::class, 'getBanners']); + Route::get('/', function () { + return 'API OK'; + }); -Route::get('/games/metadata', [GamesController::class, 'isAvailable']); + Route::get('/banners/data', [BannerController::class, 'getBanners']); + + Route::get('/games/metadata', [GamesController::class, 'isAvailable']); + + Route::fallback(function () { + return response('{"errors":[{"code":404,"message":"NotFound"}]}', 404) + ->header('Cache-Control', 'private') + ->header('Content-Type', 'application/json; charset=utf-8'); + }); -Route::fallback(function () { - return response('{"errors":[{"code":404,"message":"NotFound"}]}', 404) - ->header('Cache-Control', 'private') - ->header('Content-Type', 'application/json; charset=utf-8'); }); \ No newline at end of file