logout and info

This commit is contained in:
ntr committed 2022-08-30 23:02:34 +10:00
1 parent 4041d9827d
commit 7ea2c37116
9 files changed
+49 -34

No files matched your search

+7 -3
View File
@@ -167,11 +167,8 @@ export default function createApi(log: Log, pg: Pg, discogs, offers, events) {
ctx.assert(ctx.isAuthenticated(), 401, 'log in required'); ctx.assert(ctx.isAuthenticated(), 401, 'log in required');
const { username } = ctx.request.body; const { username } = ctx.request.body;
const user = await pg.userFindId(ctx.state.user.id); const user = await pg.userFindId(ctx.state.user.id);
const wants = await discogs.wantListSync(username, user); const wants = await discogs.wantListSync(username, user);
events.emit(Events.WantsAdded, wants); events.emit(Events.WantsAdded, wants);
ctx.response.body = wants; ctx.response.body = wants;
}); });
@@ -189,6 +186,13 @@ export default function createApi(log: Log, pg: Pg, discogs, offers, events) {
ctx.response.body = results; ctx.response.body = results;
}); });
router.post('/auth/logout', async (ctx, next) => {
ctx.assert(ctx.isAuthenticated(), 401, 'log in required');
ctx.logout();
ctx.status = 200;
ctx.body = { success: true };
});
app.use(router.routes()); app.use(router.routes());
return { return {
+3
View File
@@ -47,6 +47,9 @@ export default function createDiscogs(log: Log, pg: Pg) {
const results = await Promise.allSettled(releases.map(release => pg.wantCreate(release, user))); const results = await Promise.allSettled(releases.map(release => pg.wantCreate(release, user)));
// @ts-ignore // @ts-ignore
const additions = results.filter(r => r.status === 'fulfilled').map(r => r.value); const additions = results.filter(r => r.status === 'fulfilled').map(r => r.value);
log.info(additions);
return additions; return additions;
} }
-10
View File
@@ -39,7 +39,6 @@ export default function authRouter(log, pg: Pg) {
authRouter.post('/login', async (ctx, next) => { authRouter.post('/login', async (ctx, next) => {
await passport.authenticate('local', (err, user, info, status) => { await passport.authenticate('local', (err, user, info, status) => {
ctx.assert(user, 401, 'incorrect login'); ctx.assert(user, 401, 'incorrect login');
ctx.login(user); ctx.login(user);
ctx.status = 200; ctx.status = 200;
ctx.body = { ctx.body = {
@@ -59,15 +58,6 @@ export default function authRouter(log, pg: Pg) {
}; };
}); });
authRouter.post('/logout', async (ctx, next) => {
await passport.authenticate('local', (err, user, info, status) => {
ctx.assert(user, 401, 'incorrect login');
ctx.logout();
ctx.status = 200;
ctx.body = { success: true };
})(ctx, next);
});
authRouter.post('/register', async (ctx, next) => { authRouter.post('/register', async (ctx, next) => {
const { discogs, email, password } = ctx.request.body; const { discogs, email, password } = ctx.request.body;
// fetch discogs data if they have it // fetch discogs data if they have it
+4
View File
@@ -72,6 +72,10 @@ const actions = {
}); });
}, },
postLogout: async function postLogout() {
return api.post('/auth/logout', {});
},
postRegister: async function postRegister(email, password) { postRegister: async function postRegister(email, password) {
return api.post('/auth/register', { return api.post('/auth/register', {
email, email,
+8 -1
View File
@@ -32,9 +32,16 @@ function App() {
route('/search'); route('/search');
} }
async function logout(e) {
e.preventDefault();
await actions.postLogout();
route('/login');
setUser(null);
}
return ( return (
<main id="app"> <main id="app">
<Header user={user} /> <Header user={user} logout={logout} />
<Router> <Router>
<Route path="/" component={Home} /> <Route path="/" component={Home} />
<Route path="/login" component={Login} success={loginSuccess} mode="login" /> <Route path="/login" component={Login} success={loginSuccess} mode="login" />
+12 -3
View File
@@ -1,7 +1,9 @@
import { h } from 'preact'; import { h } from 'preact';
// import { Link } from 'preact-router/match'; import { route } from 'preact-router';
const Header = ({ user }) => { import actions from './../actions';
const Header = ({ user, logout }) => {
const nav = () => ( const nav = () => (
<nav> <nav>
<a href="/">Offers</a> <a href="/">Offers</a>
@@ -22,14 +24,21 @@ const Header = ({ user }) => {
<a href="/bundles">Bundles</a> <a href="/bundles">Bundles</a>
<a href='/offers/acp'>Offers ACP</a> <a href='/offers/acp'>Offers ACP</a>
</nav> </nav>
)
const userNav = () => (
<nav>
<a href="/account">Account</a>
<a href="/auth/logout" onClick={(e) => logout(e)}>Logout</a>
</nav>
) )
return ( return (
<header> <header>
{user ? nav() : anonNav()} {user ? nav() : anonNav()}
<div></div>
{user ? adminNav() : null} {user ? adminNav() : null}
{user ? userNav() : null}
</header> </header>
); );
} }
+5 -7
View File
@@ -8,8 +8,6 @@ const Login = ({ success, mode }) => {
const [confirmPassword, setConfirmPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState('');
const [error, setError] = useState(''); const [error, setError] = useState('');
console.log(confirmPassword);
async function postLogin() { async function postLogin() {
const [error, user] = await actions.postLogin(email, password); const [error, user] = await actions.postLogin(email, password);
if (error) return setError(error); if (error) return setError(error);
@@ -38,15 +36,15 @@ const Login = ({ success, mode }) => {
<form action=""> <form action="">
<div class="item"> <div class="item">
<label for="email">email</label> <label for="email">email</label>
<input type="email" name="email" id="email" value={email} required onChange={(e) => setEmail((e.target as HTMLInputElement).value)} /> <input type="email" name="email" id="email" value={email} required onInput={(e) => setEmail((e.target as HTMLInputElement).value)} />
</div> </div>
<div class="item"> <div class="item">
<label for="password">password</label> <label for="password">password</label>
<input type="password" name="password" id="password" value={password} required onChange={(e) => setConfirmPassword((e.target as HTMLInputElement).value)} /> <input type="password" name="password" id="password" value={password} required onInput={(e) => setConfirmPassword((e.target as HTMLInputElement).value)} />
</div> </div>
<div class="item"> <div class="item">
<label for="password">confirm password</label> <label for="password">confirm password</label>
<input type="password" name="password" id="password" value={password} required onChange={(e) => setConfirmPassword((e.target as HTMLInputElement).value)} /> <input type="password" name="password" id="password" value={password} required onInput={(e) => setConfirmPassword((e.target as HTMLInputElement).value)} />
</div> </div>
<div class="item"> <div class="item">
<input type="submit" value="register" onClick={handleSubmit} /> <input type="submit" value="register" onClick={handleSubmit} />
@@ -62,11 +60,11 @@ const Login = ({ success, mode }) => {
<form action=""> <form action="">
<div class="item"> <div class="item">
<label for="email">email</label> <label for="email">email</label>
<input type="email" name="email" id="email" value={email} required onChange={(e) => setEmail((e.target as HTMLInputElement).value)} /> <input type="email" name="email" id="email" value={email} required onInput={(e) => setEmail((e.target as HTMLInputElement).value)} />
</div> </div>
<div class="item"> <div class="item">
<label for="password">password</label> <label for="password">password</label>
<input type="password" name="password" id="password" value={password} required onChange={(e) => setPassword((e.target as HTMLInputElement).value)} /> <input type="password" name="password" id="password" value={password} required onInput={(e) => setPassword((e.target as HTMLInputElement).value)} />
</div> </div>
<div class="item"> <div class="item">
<input type="submit" value="login" onClick={handleSubmit} /> <input type="submit" value="login" onClick={handleSubmit} />
+9 -9
View File
@@ -37,28 +37,28 @@ const User = () => {
const [title, setTitle] = useState(''); const [title, setTitle] = useState('');
const [username, setUsername] = useState(''); const [username, setUsername] = useState('');
const [results, setResults] = useState([]); const [results, setResults] = useState([]);
const [noResults, setNoResults] = useState(false); const [infoText, setInfoText] = useState('');
async function fetchResults() { async function fetchResults() {
const [error, results] = await actions.postWantSearch(artist, title); const [error, results] = await actions.postWantSearch(artist, title);
if (results.length === 0) { if (results.length === 0) {
setResults([]); setResults([]);
return setNoResults(true); return setInfoText('No results');
} }
setNoResults(false); setInfoText('');
setResults(results); setResults(results);
} }
async function submitWantlist() { async function submitWantlist() {
const [error, wants] = await actions.postDiscogs(username); const [error, wants] = await actions.postDiscogs(username);
if (results.length === 0) { if (wants.length === 0) {
setResults([]); setResults([]);
return setNoResults(true); return setInfoText('No new additions');
} }
console.log('synced', wants.length, 'wants'); setInfoText(`Added ${wants.length} items to your list.`);
} }
const searchRef = useRef<HTMLInputElement>() const searchRef = useRef<HTMLInputElement>()
@@ -81,8 +81,8 @@ const User = () => {
? <button onClick={() => window.scrollTo(0, 0)}> top </button> ? <button onClick={() => window.scrollTo(0, 0)}> top </button>
: null; : null;
const noResultsEl = noResults const infoEl = infoText
? <article>No Results</article> ? <article><div></div><div>{infoText}</div></article>
: null; : null;
return ( return (
@@ -108,7 +108,7 @@ const User = () => {
</div> </div>
<div /> <div />
<div> <div>
{noResultsEl} {infoEl}
{results.map(Result)} {results.map(Result)}
{topEl} {topEl}
</div> </div>
+1 -1
View File
@@ -11,7 +11,7 @@ services:
api: api:
image: node:16 image: node:16
working_dir: /opt/mcrates/api working_dir: /opt/mcrates/api
entrypoint: sleep 10000 entrypoint: npm run test:watch
depends_on: depends_on:
- pg - pg
environment: environment: