From 3f2fd351956ad4e84f68b6043083da23faeae9b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Delattre?= Date: Sun, 13 Aug 2017 09:00:18 +0200 Subject: [PATCH] Only show the activation page for unactivated users --- src/internal/auth/auth.go | 1 + src/internal/auth/middleware.go | 8 +++++- src/internal/users/handlers.go | 5 ++-- src/internal/users/users.go | 5 ++++ src/public/js/app.js | 2 ++ src/public/js/components/navbar.js | 29 +++++++++++++------- src/public/js/components/users/activation.js | 16 +++++++++++ src/public/js/reducers/users.js | 2 ++ src/public/js/routes.js | 28 ++++++++++++++++--- 9 files changed, 79 insertions(+), 17 deletions(-) create mode 100644 src/public/js/components/users/activation.js diff --git a/src/internal/auth/auth.go b/src/internal/auth/auth.go index b072cb1..0fefd82 100644 --- a/src/internal/auth/auth.go +++ b/src/internal/auth/auth.go @@ -30,6 +30,7 @@ type User interface { GetHash() string HasRole(string) bool IsAdmin() bool + IsActivated() bool } // Authorizer handle sesssion diff --git a/src/internal/auth/middleware.go b/src/internal/auth/middleware.go index 758cfb9..1ae088f 100644 --- a/src/internal/auth/middleware.go +++ b/src/internal/auth/middleware.go @@ -74,7 +74,13 @@ func (m *MiddlewareRole) ServeHTTP(w http.ResponseWriter, r *http.Request, next return } - m.log.Debug("user has the role, continuing") + if !user.IsActivated() { + // return unauthorized + http.Error(w, "User is not activated", http.StatusUnauthorized) + return + } + + m.log.Debug("user has the role and is activated, continuing") next(w, r) } diff --git a/src/internal/users/handlers.go b/src/internal/users/handlers.go index 6adf924..d07223c 100644 --- a/src/internal/users/handlers.go +++ b/src/internal/users/handlers.go @@ -81,8 +81,9 @@ func LoginPOSTHandler(e *web.Env, w http.ResponseWriter, r *http.Request) error // Issued at "iat": time.Now().Unix(), // Private claims - "username": user.GetName(), - "isAdmin": user.IsAdmin(), + "username": user.GetName(), + "isAdmin": user.IsAdmin(), + "isActivated": user.IsActivated(), }) // Sign the token diff --git a/src/internal/users/users.go b/src/internal/users/users.go index 880b0c4..d33e52d 100644 --- a/src/internal/users/users.go +++ b/src/internal/users/users.go @@ -251,3 +251,8 @@ func (u *User) HasRole(role string) bool { func (u *User) IsAdmin() bool { return u.HasRole(AdminRole) } + +// IsActivated checks if a user is activated +func (u *User) IsActivated() bool { + return u.Activated +} diff --git a/src/public/js/app.js b/src/public/js/app.js index 0fafb56..2f53839 100644 --- a/src/public/js/app.js +++ b/src/public/js/app.js @@ -47,6 +47,7 @@ function mapStateToProps(state) { return { username: state.userStore.get("username"), isAdmin: state.userStore.get("isAdmin"), + isActivated: state.userStore.get("isActivated"), torrentCount: torrentCount, alerts: state.alerts, } @@ -62,6 +63,7 @@ function Main(props) { diff --git a/src/public/js/components/navbar.js b/src/public/js/components/navbar.js index 5c44c5d..5c38db6 100644 --- a/src/public/js/components/navbar.js +++ b/src/public/js/components/navbar.js @@ -41,6 +41,9 @@ export default class AppNavBar extends React.PureComponent { this.setState({ expanded: value }); } render() { + const loggedAndActivated = (this.state.userLoggedIn && this.props.isActivated); + const displayShowsSearch = (this.state.displayShowsSearch && loggedAndActivated); + const displayMoviesSearch = (this.state.displayMoviesSearch && loggedAndActivated); return (
@@ -51,20 +54,24 @@ export default class AppNavBar extends React.PureComponent { - {this.state.userLoggedIn && + {loggedAndActivated && } - {this.state.userLoggedIn && + {loggedAndActivated && } - {this.state.userLoggedIn && + {loggedAndActivated && } - {this.state.userLoggedIn && + {loggedAndActivated && } - - {(this.state.displayMoviesSearch && this.state.userLoggedIn) && + + {displayMoviesSearch && } - {(this.state.displayShowsSearch && this.state.userLoggedIn) && + {displayShowsSearch && Admin Panel } - - Edit - + {props.isActivated && + + Edit + + } Logout diff --git a/src/public/js/components/users/activation.js b/src/public/js/components/users/activation.js new file mode 100644 index 0000000..a6f5288 --- /dev/null +++ b/src/public/js/components/users/activation.js @@ -0,0 +1,16 @@ +import React from "react" + +function UserActivation(props) { + return ( +
+
+
+

Waiting for activation

+
+

Hang tight! Your user will soon be activated by the administrators of this site.

+
+
+
+ ); +} +export default UserActivation; diff --git a/src/public/js/reducers/users.js b/src/public/js/reducers/users.js index 572f90c..8e133e7 100644 --- a/src/public/js/reducers/users.js +++ b/src/public/js/reducers/users.js @@ -7,6 +7,7 @@ const defaultState = Map({ loading: false, username: "", isAdmin: false, + isActivated: false, isLogged: false, polochonToken: "", polochonUrl: "", @@ -46,6 +47,7 @@ function updateFromToken(state, token) { userLoading: false, isLogged: true, isAdmin: decodedToken.isAdmin, + isActivated: decodedToken.isActivated, username: decodedToken.username, })) } diff --git a/src/public/js/routes.js b/src/public/js/routes.js index 4bde093..163ce69 100644 --- a/src/public/js/routes.js +++ b/src/public/js/routes.js @@ -3,6 +3,7 @@ import ShowList from "./components/shows/list" import ShowDetails from "./components/shows/details" import UserLoginForm from "./components/users/login" import UserEdit from "./components/users/edit" +import UserActivation from "./components/users/activation" import UserSignUp from "./components/users/signup" import TorrentList from "./components/torrents/list" import AdminView from "./components/admins/users" @@ -42,15 +43,20 @@ function isLoggedIn() { return false } +function isActivated() { + const state = store.getState(); + return state.userStore.get("isActivated"); +} + var pollingTorrentsId; const loginCheck = function(nextState, replace, next, f = null) { const loggedIn = isLoggedIn(); if (!loggedIn) { - replace("/users/login"); + replace("/users/login"); + } else if (!isActivated()) { + replace("/users/activation"); } else { - if (f) { - f(); - } + if (f) { f(); } // Poll torrents once logged if (!pollingTorrentsId) { @@ -104,6 +110,20 @@ export default function getRoutes(App) { }); }, }, + { + path: "/users/activation", + component: UserActivation, + onEnter: function(nextState, replace, next) { + if (!isLoggedIn()) { + replace('/users/login'); + } + if (isActivated()) { + // User is already activated, redirect him to the default route + replace(defaultRoute); + } + next(); + }, + }, { path: "/users/logout", onEnter: function(nextState, replace, next) {