From 0fe28d3db896522a23e74144d488cee74858fa28 Mon Sep 17 00:00:00 2001 From: Armin Friedl Date: Sun, 24 May 2020 17:06:59 +0200 Subject: [PATCH] Fling user access Authentication for protected flings: - Unlock screen - Authentication backend - Routes Direct redirect for unprotected flings. --- .../authentication/AuthenticationService.java | 7 +- .../authentication/dto/UserAuthDto.java | 2 +- .../friedl/fling/service/FlingService.java | 1 + web/fling/src/App.jsx | 34 +++++++-- .../admin/{Fling.jsx => FlingAdmin.jsx} | 2 +- .../src/components/admin/FlingArtifacts.jsx | 12 ++++ web/fling/src/components/admin/Login.jsx | 2 +- web/fling/src/components/admin/New.jsx | 1 + web/fling/src/components/user/Error.jsx | 26 +++++++ web/fling/src/components/user/FlingUser.jsx | 14 ++++ web/fling/src/components/user/Unlock.jsx | 70 +++++++++++++++++++ web/fling/src/style/_variables.scss | 3 +- web/fling/src/style/fling.scss | 16 +++++ 13 files changed, 179 insertions(+), 11 deletions(-) rename web/fling/src/components/admin/{Fling.jsx => FlingAdmin.jsx} (94%) create mode 100644 web/fling/src/components/user/Error.jsx create mode 100644 web/fling/src/components/user/FlingUser.jsx create mode 100644 web/fling/src/components/user/Unlock.jsx diff --git a/service/fling/src/main/java/net/friedl/fling/security/authentication/AuthenticationService.java b/service/fling/src/main/java/net/friedl/fling/security/authentication/AuthenticationService.java index d0a4c55..62ab908 100644 --- a/service/fling/src/main/java/net/friedl/fling/security/authentication/AuthenticationService.java +++ b/service/fling/src/main/java/net/friedl/fling/security/authentication/AuthenticationService.java @@ -51,16 +51,17 @@ public class AuthenticationService { } public String authenticate(UserAuthDto userAuth) { - Long flingId = userAuth.getFlingId(); + var fling = flingService.findFlingByShareId(userAuth.getShareId()) + .orElseThrow(); String authCode = userAuth.getCode(); - if (!flingService.hasAuthCode(flingId, authCode)) { + if (!flingService.hasAuthCode(fling.getId(), authCode)) { throw new AccessDeniedException("Wrong fling code"); } return makeBaseBuilder() .setSubject("user") - .claim("fid", flingId) + .claim("sid", fling.getShareUrl()) .compact(); } diff --git a/service/fling/src/main/java/net/friedl/fling/security/authentication/dto/UserAuthDto.java b/service/fling/src/main/java/net/friedl/fling/security/authentication/dto/UserAuthDto.java index a41d899..0c714f3 100644 --- a/service/fling/src/main/java/net/friedl/fling/security/authentication/dto/UserAuthDto.java +++ b/service/fling/src/main/java/net/friedl/fling/security/authentication/dto/UserAuthDto.java @@ -4,6 +4,6 @@ import lombok.Data; @Data public class UserAuthDto { - Long flingId; + String shareId; String code; } diff --git a/service/fling/src/main/java/net/friedl/fling/service/FlingService.java b/service/fling/src/main/java/net/friedl/fling/service/FlingService.java index 403e788..12b9542 100644 --- a/service/fling/src/main/java/net/friedl/fling/service/FlingService.java +++ b/service/fling/src/main/java/net/friedl/fling/service/FlingService.java @@ -48,6 +48,7 @@ public class FlingService { } var flingEntity = flingMapper.map(flingDto); + flingEntity.setAuthCode(hashKey(flingEntity.getAuthCode())); flingEntity = flingRepository.save(flingEntity); return flingEntity.getId(); } diff --git a/web/fling/src/App.jsx b/web/fling/src/App.jsx index ae869fc..3f9927c 100644 --- a/web/fling/src/App.jsx +++ b/web/fling/src/App.jsx @@ -3,17 +3,23 @@ import React from 'react'; import {Switch, Route, Redirect} from "react-router-dom"; -import request, {isOwner} from './util/request'; +import request, {isOwner, isUser} from './util/request'; import Login from './components/admin/Login'; -import Fling from './components/admin/Fling'; +import FlingAdmin from './components/admin/FlingAdmin'; + +import Unlock from './components/user/Unlock'; +import FlingUser from './components/user/FlingUser'; export default () => { return ( - - + + + + + Not implemented ); @@ -33,3 +39,23 @@ function OwnerRoute({ children, ...rest }) { /> ); } + +// A wrapper for that redirects to the unlock +// screen if the fling is protected +function UserRoute({ children, ...rest }) { + return ( + { + log.info(request.defaults); + log.info(match); + log.info(location); + let x = {from: location, shareId: match.params.shareId}; + + if(isOwner()) { return children; } + else if(isUser(match.params.shareId)) { return children; } + else { return ; } + }} + /> + ); +} diff --git a/web/fling/src/components/admin/Fling.jsx b/web/fling/src/components/admin/FlingAdmin.jsx similarity index 94% rename from web/fling/src/components/admin/Fling.jsx rename to web/fling/src/components/admin/FlingAdmin.jsx index 167d383..9024fd2 100644 --- a/web/fling/src/components/admin/Fling.jsx +++ b/web/fling/src/components/admin/FlingAdmin.jsx @@ -7,7 +7,7 @@ import FlingContent from './FlingContent'; import {useParams, BrowserRouter} from 'react-router-dom'; -export default function Fling() { +export default function FlingAdmin() { let { fling } = useParams(); return( diff --git a/web/fling/src/components/admin/FlingArtifacts.jsx b/web/fling/src/components/admin/FlingArtifacts.jsx index 9b51391..6bf066d 100644 --- a/web/fling/src/components/admin/FlingArtifacts.jsx +++ b/web/fling/src/components/admin/FlingArtifacts.jsx @@ -64,11 +64,22 @@ function FlingArtifactRow(props) { ); } +function FlingInfo(props) { + return( +
+ { /* Add some infos about the fling */ } +
+ ); +} + export default function FlingArtifacts(props) { const [artifacts, setArtifacts] = useState([]); useEffect(getArtifacts, [props.activeFling]); return ( +
+ + @@ -82,6 +93,7 @@ export default function FlingArtifacts(props) { {artifacts}
+
); function getArtifacts() { diff --git a/web/fling/src/components/admin/Login.jsx b/web/fling/src/components/admin/Login.jsx index d63e784..28e8380 100644 --- a/web/fling/src/components/admin/Login.jsx +++ b/web/fling/src/components/admin/Login.jsx @@ -6,7 +6,7 @@ import request, {setAuth} from '../../util/request'; import Error from './Error'; -export default () => { +export default function Login() { const [errors, setErrors] = useState([]); const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); diff --git a/web/fling/src/components/admin/New.jsx b/web/fling/src/components/admin/New.jsx index 9d84054..1028393 100644 --- a/web/fling/src/components/admin/New.jsx +++ b/web/fling/src/components/admin/New.jsx @@ -45,6 +45,7 @@ export default function New(props) { } function handleClose(ev) { + if(ev) ev.preventDefault(); // this is needed, otherwise a submit event is fired props.closeModalFn(); } diff --git a/web/fling/src/components/user/Error.jsx b/web/fling/src/components/user/Error.jsx new file mode 100644 index 0000000..be4d4c4 --- /dev/null +++ b/web/fling/src/components/user/Error.jsx @@ -0,0 +1,26 @@ +import React, {useState} from 'react'; +import classNames from 'classnames'; + +import log from 'loglevel'; + +export default (props) => { + function renderError() { + return ( +
+ +
Ooops!
+
  • + { props.errors.map( (err, idx) =>
      {err}
    ) } +
  • +
    + ); + } + + return ( + <> + { props.errors.length > 0 && !props.below ? renderError() : "" } + { props.children } + { props.errors.length > 0 && props.below ? renderError() : "" } + + ); +} diff --git a/web/fling/src/components/user/FlingUser.jsx b/web/fling/src/components/user/FlingUser.jsx new file mode 100644 index 0000000..1532a57 --- /dev/null +++ b/web/fling/src/components/user/FlingUser.jsx @@ -0,0 +1,14 @@ +import log from 'loglevel'; +import React, {useState} from 'react'; + +import {useParams, BrowserRouter} from 'react-router-dom'; + +export default function FlingAdmin() { + let { fling } = useParams(); + + return( +
    + Hello +
    + ); +} diff --git a/web/fling/src/components/user/Unlock.jsx b/web/fling/src/components/user/Unlock.jsx new file mode 100644 index 0000000..55c09d2 --- /dev/null +++ b/web/fling/src/components/user/Unlock.jsx @@ -0,0 +1,70 @@ +import log from 'loglevel'; +import React, {useState, useEffect} from 'react'; +import {useHistory, useLocation} from 'react-router-dom'; + +import request, {setAuth} from '../../util/request'; + +import Error from './Error'; + +export default function Unlock() { + const [errors, setErrors] = useState([]); + const [authCode, setAuthCode] = useState(""); + const history = useHistory(); + const location = useLocation(); + const { from, shareId } = location.state || { from: { pathname: "/admin" }, shareId: "" }; + + useEffect(() => setAuth(null), []); + + useEffect(() => { + request.post("/auth/user", {"shareId": location.state.shareId}) + .then(response => { + log.info("Fling is not protected. Logged in successfully."); + setAuth(response.data); + history.replace(location.state.from); + }) + .catch(err => {/* ignored */}); + }, [location]); + + return ( +
    +
    +
    +

    This Fling is locked.

    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    + ); + + function handleSubmit(ev) { + ev.preventDefault(); + + request.post("/auth/user", {"shareId": shareId, "code": authCode}) + .then(response => { + log.info("Logged in successfully"); + setAuth(response.data); + history.replace(from); + }) + .catch(error => { + log.error(error); + let response = error.response; + response.data && response.data.message && setErrors( prev => [response.data.message, ...prev] ); + }); + }; + + function handleChange(ev) { + let val = ev.target.value; + setAuthCode(val); + }; + + function clearErrors() { + setErrors([]); + } +} diff --git a/web/fling/src/style/_variables.scss b/web/fling/src/style/_variables.scss index 33ba03e..e499e0e 100644 --- a/web/fling/src/style/_variables.scss +++ b/web/fling/src/style/_variables.scss @@ -8,10 +8,11 @@ $light-grey: #ebeced; $dark-grey: #464748; $red: #e53e3e; $black: #323334; +$lighter-grey: #E9F2F9; // Semantic colors $primary-color: #4693d2; -$canvas-base-color: $grey; +$canvas-base-color: white; $navbar-base-color: $black; $navbar-color: $light-grey; diff --git a/web/fling/src/style/fling.scss b/web/fling/src/style/fling.scss index 5b9eb76..6dea736 100644 --- a/web/fling/src/style/fling.scss +++ b/web/fling/src/style/fling.scss @@ -37,6 +37,22 @@ body { margin-top: 0.25rem; } +/**********\ +| Unlock | +\**********/ + +#auth-code { + font-size: 1.1rem; + height: 1.8rem; + vertical-align: middle; +} + +#auth-code-form .btn { + font-size: 1.1rem; + height: 1.8rem; + vertical-align: middle; +} + /*********\ | Navbar | \*********/