diff --git a/api/auth.js b/api/auth.js index a4b788e..d422193 100644 --- a/api/auth.js +++ b/api/auth.js @@ -57,11 +57,13 @@ export default (R: Router, $: AppContext) => { }) R.get('/api/auth/redirect', async (ctx: Context) => { + const { r } = ctx.query // check if already authed if (await $.auth.isLoggedIn(ctx, { refresh: true })) { - return ctx.redirect('/') + return ctx.redirect(r || '/') } + ctx.session.oauthRedirect = r const url = $.discord.getAuthUrl(ksuid.randomSync().string) if (ctx.query.url === '✔️') { ctx.body = { url } @@ -72,11 +74,13 @@ export default (R: Router, $: AppContext) => { }) R.get('/api/oauth/callback', async (ctx: Context) => { + const { code, state } = ctx.query + const { oauthRedirect: r } = ctx.session + delete ctx.session.oauthRedirect if (await $.auth.isLoggedIn(ctx)) { - return ctx.redirect('/') + return ctx.redirect(r || '/') } - const { code, state } = ctx.query if (code == null) { ctx.status = 400 return @@ -95,7 +99,7 @@ export default (R: Router, $: AppContext) => { const tokens = await $.discord.getAuthToken(code) const user = await $.discord.getUserFromToken(tokens.access_token) $.auth.injectSessionFromOAuth(ctx, tokens, user.id) - return ctx.redirect('/') + return ctx.redirect(r || '/') } catch (e) { log.error('token and auth fetch failure', e) ctx.status = 400 diff --git a/ui/pages/_internal/_server.js b/ui/pages/_internal/_server.js index a54434a..e10a663 100644 --- a/ui/pages/_internal/_server.js +++ b/ui/pages/_internal/_server.js @@ -3,8 +3,17 @@ import * as React from 'react' import Head from 'next/head' import type { PageProps } from '../../types' import SocialCards from '../../components/social-cards' +import redirect from '../../lib/redirect' export default class Server extends React.Component { + static async getInitialProps (ctx: *, rpc: *, router: *) { + if (ctx.user == null) { + redirect(ctx, `/auth/login?r=${router.asPath}`) + } + + ctx.robots = 'NOINDEX, NOFOLLOW' + } + render () { return (
diff --git a/ui/pages/auth/login.js b/ui/pages/auth/login.js index 7913aa0..24e72e4 100644 --- a/ui/pages/auth/login.js +++ b/ui/pages/auth/login.js @@ -5,16 +5,27 @@ import MediaQuery from '../../kit/media' import DiscordButton from '../../components/discord-button' import RPC from '../../config/rpc' import redirect from '../../lib/redirect' +import dynamic from 'next/dynamic' +import type { PageProps, ServerSlug } from '../../types' type AuthLoginState = { humanCode: string, waiting: boolean } +type AuthLoginProps = PageProps & { + redirect: ?string, + redirectSlug: ?ServerSlug +} + const Wrapper = styled.div` display: flex; justify-content: center; padding-top: 3em; + width: 400px; + max-width: calc(98vw - 10px); + margin: 0 auto; + text-align: center; ${() => MediaQuery({ md: ` padding-top: 0; @@ -76,16 +87,60 @@ const HiderButton = styled.button` pointer-events: none; } ` +const SlugWrapper = styled.div` + padding-bottom: 2em; + text-align: center; +` -export default class AuthLogin extends React.Component<{}, AuthLoginState> { +const DiscordGuildPic = dynamic(() => import('../../components/discord-guild-pic')) +const StyledDGP = styled(DiscordGuildPic)` + border-radius: 100%; + border: 2px solid rgba(0,0,0,0.2); + height: 4em; + margin-top: 1em; +` + +const ServerName = styled.span` + font-weight: bold; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + width: 370px; + display: block; +` + +const Slug = (slug: ServerSlug) => + +
Hey there.
{slug.name} uses Roleypoly to manage its roles. +
+ +export default class AuthLogin extends React.Component { state = { humanCode: '', waiting: false } - static async getInitialProps (ctx, rpc) { + static async getInitialProps (ctx: *, rpc: typeof RPC, router: *) { + let { r } = (router.query: { r: string }) + if (ctx.user != null) { - redirect(ctx, '/') + redirect(ctx, r || '/') + } + + ctx.robots = 'NOINDEX, NOFOLLOW' + + if (r != null) { + let redirectSlug = null + if (r.startsWith('/s/') && r !== '/s/add') { + redirectSlug = await rpc.getServerSlug(r.replace('/s/', '')) + } + return { redirect: r, redirectSlug } + } + } + + componentDidMount () { + if (this.props.redirect != null) { + this.props.router.replace(this.props.router.pathname) } } @@ -98,9 +153,9 @@ export default class AuthLogin extends React.Component<{}, AuthLoginState> { try { const result = await RPC.checkAuthChallenge(this.state.humanCode) if (result === true) { - redirect(null, '/') + redirect(null, this.props.redirect || '/') } - } finally { + } catch (e) { this.setState({ waiting: false }) } } @@ -108,7 +163,8 @@ export default class AuthLogin extends React.Component<{}, AuthLoginState> { render () { return
- Sign in with Discord + {(this.props.redirectSlug != null) ? : null} + Sign in with Discord
Or, send a DM to roleypoly#3712 saying: login