Redesigned the UIs with daisyui (#23)

This commit is contained in:
Kiran K 2022-07-27 02:58:46 +05:30 committed by GitHub
parent c73dec8f12
commit f915a7672d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 429 additions and 440 deletions

2
.gitignore vendored
View File

@ -36,3 +36,5 @@ yarn-error.log*
*.tsbuildinfo *.tsbuildinfo
.env .env
key.pem
public.crt

View File

@ -2,8 +2,8 @@ import Link from 'next/link';
export default function Header() { export default function Header() {
return ( return (
<header className='body-font text-gray-600'> <header className='body-font border-b text-gray-600'>
<div className='container mx-auto flex flex-col flex-wrap items-center p-5 md:flex-row'> <div className='container mx-auto flex flex-col flex-wrap items-center justify-between space-y-3 py-3 md:flex-row'>
<Link href='/'> <Link href='/'>
<a className='title-font flex items-center font-medium text-gray-900 md:mb-0'> <a className='title-font flex items-center font-medium text-gray-900 md:mb-0'>
<svg <svg
@ -20,25 +20,23 @@ export default function Header() {
<span className='ml-3 text-2xl'>Mock SAML</span> <span className='ml-3 text-2xl'>Mock SAML</span>
</a> </a>
</Link> </Link>
<nav className='mt-2 flex flex-col flex-wrap items-center text-base md:ml-auto md:mt-0 md:items-end'> <div className='flex flex-col items-center md:flex-row'>
<span className='ml-2 text-sm text-gray-500 '> <span className='mr-5'>
Made with <span className='text-[#e25555]'>&#9829;</span>
<a <a
href='https://boxyhq.com/' className='btn btn-outline btn-sm'
className='ml-1 text-gray-600' href='https://github.com/boxyhq/jackson'
rel='noopener noreferrer' rel='noopener noreferrer'
target='_blank'> target='_blank'>
Integrate SAML with a few lines of code
</a>
</span>
<span>
Made with <span className='text-red-500'>&#9829;</span>{' '}
<a href='https://boxyhq.com/' rel='noopener noreferrer' target='_blank'>
<strong>BoxyHQ</strong> <strong>BoxyHQ</strong>
</a> </a>
</span> </span>
<a </div>
className='leading-5 underline hover:text-gray-900'
href='https://github.com/boxyhq/jackson'
rel='noopener noreferrer'
target='_blank'>
Integrate SAML with a few lines of code
</a>
</nav>
</div> </div>
</header> </header>
); );

461
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@
}, },
"dependencies": { "dependencies": {
"@boxyhq/saml20": "1.0.1", "@boxyhq/saml20": "1.0.1",
"daisyui": "^2.19.0",
"next": "12.1.4", "next": "12.1.4",
"react": "18.0.0", "react": "18.0.0",
"react-dom": "18.0.0", "react-dom": "18.0.0",

View File

@ -4,6 +4,76 @@ import React from 'react';
import config from '../lib/env'; import config from '../lib/env';
import { IdPMetadata } from '../types'; import { IdPMetadata } from '../types';
const Home: React.FC<{ metadata: IdPMetadata }> = ({ metadata }) => {
const { ssoUrl, entityId, certificate } = metadata;
return (
<div className='flex min-h-full items-center justify-center'>
<div className='flex w-full max-w-4xl flex-col px-3'>
<h1 className='mb-20 text-center text-2xl font-extrabold text-gray-900'>
A free SAML 2.0 Identity Provider for testing SAML SSO integrations.
</h1>
<div className='space-y-4'>
<div className='flex justify-between'>
<Link href='/api/saml/metadata/download'>
<a className='btn btn-active btn-primary'>
<svg
className='mr-1 inline-block h-6 w-6'
fill='none'
viewBox='0 0 24 24'
stroke='currentColor'
aria-hidden
strokeWidth='2'>
<path
strokeLinecap='round'
strokeLinejoin='round'
d='M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4'
/>
</svg>
Download Metadata
</a>
</Link>
<Link href='/saml/login'>
<a className='btn btn-outline btn-primary'>Test IdP Login</a>
</Link>
</div>
<div className='border-2 p-3'>
<h2 className='mb-5 text-center text-2xl font-bold text-gray-900'>Mock SAML Metadata</h2>
<div className='grid grid-cols-2 gap-y-5 gap-x-5'>
<div className='form-control'>
<label className='label'>
<span className='label-text font-bold'>SSO URL</span>
</label>
<input type='text' defaultValue={ssoUrl} className='input input-bordered' disabled />
</div>
<div className='form-control'>
<label className='label'>
<span className='label-text font-bold'>Entity ID</span>
</label>
<input type='text' defaultValue={entityId} className='input input-bordered' disabled />
</div>
<div className='form-control col-span-2 w-full'>
<label className='label'>
<span className='label-text font-bold'>Certificate</span>
</label>
<textarea
className='textarea textarea-bordered h-48'
defaultValue={certificate}
disabled></textarea>
</div>
</div>
</div>
<div className='alert alert-error'>
<div>
<span className='text-white'>Caution: Not for production use.</span>
</div>
</div>
</div>
</div>
</div>
);
};
export const getServerSideProps: GetServerSideProps = async () => { export const getServerSideProps: GetServerSideProps = async () => {
const metadata: IdPMetadata = { const metadata: IdPMetadata = {
ssoUrl: config.ssoUrl, ssoUrl: config.ssoUrl,
@ -18,73 +88,4 @@ export const getServerSideProps: GetServerSideProps = async () => {
}; };
}; };
const Home: React.FC<{ metadata: IdPMetadata }> = ({ metadata }) => {
const { ssoUrl, entityId, certificate } = metadata;
return (
<section className='body-font text-gray-600'>
<div className='container mx-auto px-5 py-8'>
<div className='mb-5 flex w-full flex-col text-center'>
<p className='mx-auto text-lg font-medium leading-relaxed lg:w-2/3'>
A free SAML 2.0 Identity Provider for testing SAML SSO integrations.
<sup className='text-xl text-orange-600'>*</sup>
<a
className='leading-5 underline hover:text-gray-900'
href='https://github.com/boxyhq/mock-saml'
rel='noopener noreferrer'
target='_blank'>
Open-source and free
</a>
</p>
<div className='mx-auto mt-4 flex w-full justify-center px-8 lg:w-2/3'>
<Link href='/saml/login'>
<a className='button min-w-[14rem] py-3 text-xl tracking-wide'>Test IdP Login</a>
</Link>
</div>
</div>
<h2 className='title-font mt-9 text-center text-lg font-medium text-gray-900 sm:text-3xl'>
Mock SAML Metadata
</h2>
<div className='mx-auto mt-5 flex w-full space-x-6 px-8 lg:w-2/3'>
<div className='relative flex-1'>
<label className='text-sm leading-7 text-gray-600'>SSO URL</label>
<input disabled type='text' defaultValue={ssoUrl} className='input w-full' />
</div>
<div className='relative flex-1'>
<label className='text-sm leading-7 text-gray-600'>Entity ID</label>
<input disabled type='text' defaultValue={entityId} className='input w-full' />
</div>
</div>
<div className='mx-auto mt-5 flex w-full px-8 lg:w-2/3'>
<div className='relative w-full'>
<label className='text-sm leading-7 text-gray-600'>Certificate</label>
<textarea disabled rows={5} defaultValue={certificate} className='input w-full'></textarea>
</div>
</div>
<div className='mx-auto mt-5 flex w-full justify-center px-8 lg:w-2/3'>
<Link href='/api/saml/metadata/download'>
<a className='button-secondary'>
<svg
className='mr-1 inline-block h-6 w-6'
fill='none'
viewBox='0 0 24 24'
stroke='currentColor'
aria-hidden
strokeWidth='2'>
<path
strokeLinecap='round'
strokeLinejoin='round'
d='M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4'
/>
</svg>
Download Metadata
</a>
</Link>
</div>
<p className='mt-3 text-center text-lg text-orange-600'>* Caution: Not for production use</p>
</div>
</section>
);
};
export default Home; export default Home;

View File

@ -6,7 +6,6 @@ import { useEffect, useRef, useState } from 'react';
export default function Login() { export default function Login() {
const router = useRouter(); const router = useRouter();
const { id, audience, acsUrl, providerName, relayState } = router.query; const { id, audience, acsUrl, providerName, relayState } = router.query;
const isRouteReady = router.isReady;
const [state, setState] = useState({ const [state, setState] = useState({
username: 'jackson', username: 'jackson',
@ -16,8 +15,8 @@ export default function Login() {
}); });
const acsUrlInp = useRef<HTMLInputElement>(null); const acsUrlInp = useRef<HTMLInputElement>(null);
// Set focus to email input on load
const emailInp = useRef<HTMLInputElement>(null); const emailInp = useRef<HTMLInputElement>(null);
useEffect(() => { useEffect(() => {
if (acsUrl && emailInp.current) { if (acsUrl && emailInp.current) {
emailInp.current.focus(); emailInp.current.focus();
@ -58,10 +57,9 @@ export default function Login() {
}); });
if (response.ok) { if (response.ok) {
const newHtml = await response.text();
const newDoc = document.open('text/html', 'replace'); const newDoc = document.open('text/html', 'replace');
newDoc.write(newHtml); newDoc.write(await response.text());
newDoc.close(); newDoc.close();
} else { } else {
document.write('Error in getting SAML response'); document.write('Error in getting SAML response');
@ -69,100 +67,117 @@ export default function Login() {
}; };
return ( return (
<div className='h-full'> <>
<Head> <Head>
<title>Mock SAML Identity Provider - Login</title> <title>Mock SAML Identity Provider - Login</title>
</Head> </Head>
<div className='relative top-20 mx-auto w-[465px] max-w-[90%] rounded-md border p-10 text-[#145698]'> <div className='flex min-h-full items-center justify-center'>
<h2 className='mb-3 text-center text-3xl font-bold'>Login</h2> <div className='flex w-full max-w-xl flex-col px-3'>
<form onSubmit={handleSubmit}> <div className='space-y-2'>
{isRouteReady ? ( <div className='border-2 p-5'>
acsUrl ? null : ( <h2 className='mb-5 text-center text-2xl font-bold text-gray-900'>SAML SSO Login</h2>
<div> <form onSubmit={handleSubmit}>
<div className='mt-5'> <div className='grid grid-cols-2 gap-y-1 gap-x-5'>
<label htmlFor='acsUrl' className='mb-2 block'> {!acsUrl ? (
ACS URL <sup>(This is where we&apos;ll post the SAML Response)</sup> <div className='col-span-2'>
</label> <div className='form-control'>
<input <label className='label'>
name='acsUrl' <span className='label-text font-bold'>ACS URL</span>
id='acsUrl' </label>
ref={acsUrlInp} <input
autoComplete='off' type='text'
type='text' className='input input-bordered'
placeholder='https://jackson-demo.boxyhq.com/api/oauth/saml' name='acsUrl'
value={state.acsUrl} id='acsUrl'
onChange={handleChange} ref={acsUrlInp}
className='input w-full' autoComplete='off'
/> placeholder='https://jackson-demo.boxyhq.com/api/oauth/saml'
value={state.acsUrl}
onChange={handleChange}
/>
<label className='label'>
<span className='label-text-alt'>This is where we will post the SAML Response</span>
</label>
</div>
<div className='form-control col-span-2'>
<label className='label'>
<span className='label-text font-bold'>Audience</span>
</label>
<input
type='text'
className='input input-bordered'
name='audience'
id='audience'
autoComplete='off'
placeholder='https://saml.boxyhq.com'
value={state.audience}
onChange={handleChange}
/>
</div>
</div>
) : null}
<div className='form-control'>
<label className='label'>
<span className='label-text font-bold'>Email</span>
</label>
<input
name='username'
id='username'
ref={emailInp}
autoComplete='off'
type='text'
placeholder='jackson'
value={state.username}
onChange={handleChange}
className='input input-bordered'
title='Please provide a mock email address'
/>
</div>
<div className='form-control'>
<label className='label'>
<span className='label-text font-bold'>Domain</span>
</label>
<select
name='domain'
id='domain'
className='select select-bordered'
onChange={handleChange}
value={state.domain}>
<option value='example.com'>@example.com</option>
<option value='example.org'>@example.org</option>
</select>
</div>
<div className='form-control col-span-2'>
<label className='label'>
<span className='label-text font-bold'>Password</span>
</label>
<input
id='password'
autoComplete='off'
type='password'
defaultValue='samlstrongpassword'
className='input input-bordered'
/>
<label className='label'>
<span className='label-text-alt'>Any password works</span>
</label>
</div>
<button className='btn btn-primary col-span-2 block'>Sign In</button>
</div> </div>
<div className='mt-5'> </form>
<label htmlFor='audience' className='mb-2 block'> </div>
Audience <div className='alert alert-info'>
</label> <div>
<input <span className='text-sm text-white'>
name='audience' This is a simulated login screen, feel free to pick any username but you are restricted to
id='audience' two domains example.com and example.org. But this should allow you to test all combinations
autoComplete='off' of your authentication and user modelling.
type='text' </span>
placeholder='https://saml.boxyhq.com' </div>
value={state.audience}
onChange={handleChange}
className='input w-full'
/>
</div>
</div>
)
) : null}
<div className='mt-5 flex items-end gap-x-1'>
<div>
<label htmlFor='username' className='mb-2 block'>
Email
</label>
<input
name='username'
id='username'
ref={emailInp}
autoComplete='off'
type='text'
placeholder='jackson'
value={state.username}
onChange={handleChange}
className='input'
title='Please provide a mock email address'
/>
</div> </div>
<select
name='domain'
id='domain'
className='select w-full'
onChange={handleChange}
value={state.domain}>
<option value='example.com'>@example.com</option>
<option value='example.org'>@example.org</option>
</select>
</div> </div>
<div className='mt-5'> </div>
<label htmlFor='password' className='mb-2 block'>
Password <sup>(Any password works)</sup>
</label>
<input
id='password'
autoComplete='off'
type='password'
defaultValue='samlstrongpassword'
className='input w-full'
/>
</div>
<button type='submit' className='button mt-8 w-full'>
Sign In
</button>
</form>
</div> </div>
<div className='relative top-20 mx-auto w-[800px] max-w-[90%] rounded-md p-10 text-[#145698]'> </>
This is a simulated login screen, feel free to pick any username but you are restricted to two domains
example.com and example.org. But this should allow you to test all combinations of your authentication
and user modelling.
</div>
</div>
); );
} }

View File

@ -25,19 +25,23 @@ a {
} }
@layer components { @layer components {
.button { .alert {
@apply block rounded-md bg-indigo-500 px-4 py-2 leading-8 text-white shadow-md hover:bg-indigo-600 focus:bg-indigo-600 focus:outline-none focus:ring-4 focus:ring-indigo-300 focus:ring-opacity-100; @apply rounded;
}
.button-secondary {
@apply button border-2 border-indigo-800 bg-white text-indigo-500 hover:bg-white hover:shadow-lg focus:bg-white;
} }
.input { .input {
@apply rounded-md border border-gray-300 bg-opacity-50 px-3 py-1 text-base leading-8 text-gray-700 outline-none transition-colors duration-200 ease-in-out focus:border-indigo-500 focus:bg-transparent focus:ring-2 focus:ring-indigo-300 disabled:bg-gray-100; @apply rounded;
}
.textarea {
@apply rounded;
} }
.select { .select {
@apply rounded-md border border-gray-300 bg-opacity-50 px-3 py-2.5 text-base leading-8 text-gray-700 outline-none transition-colors duration-200 ease-in-out focus:border-indigo-500 focus:bg-transparent focus:ring-2 focus:ring-indigo-300 disabled:bg-gray-100; @apply rounded;
}
.btn {
@apply rounded;
} }
} }

View File

@ -1,4 +1,4 @@
const colors = require("tailwindcss/colors"); const colors = require('tailwindcss/colors');
function withOpacityValue(variable) { function withOpacityValue(variable) {
return ({ opacityValue }) => { return ({ opacityValue }) => {
@ -10,18 +10,15 @@ function withOpacityValue(variable) {
} }
module.exports = { module.exports = {
darkMode: "class", darkMode: 'class',
content: [ content: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
"./pages/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
],
theme: { theme: {
colors: { colors: {
...colors, ...colors,
primary: withOpacityValue("--color-primary"), primary: withOpacityValue('--color-primary'),
secondary: withOpacityValue("--color-secondary"), secondary: withOpacityValue('--color-secondary'),
}, },
extend: {}, extend: {},
}, },
plugins: [], plugins: [require('daisyui')],
}; };