This should have been taken care of when onboarding your account, but due to a earlier
bug in the registration, a small subsection of accounts ended up in this state.
Please complete the form to give your consent, that may resolve the matter.
If it does not, please contact support so we may help you.
Consent & Privacy
)
}
/**
* A component to block access based on a FreeSewing role.
*
* Note that in an SPA, blocking access to the user is merely a matter of providing a
* more intuitive UI. That actual access control is implemented on the backend.
*
* @component
* @param {object} props - All component props
* @param {React.FC} [props.Link = false] - An optional framework-specific Link component
* @param {string} [props.role = admin] - The role required to access the content. Typically admin or user.
* @param {JSX.Element} props.children - The component children, will be rendered if props.js is not set
* @returns {JSX.Element}
*/
export const RoleBlock = ({ children, role = 'admin', Link = false }) => {
if (!Link) Link = DefaultLink
const requiredRole = role
const { account, setAccount, token, admin, stopImpersonating, signOut } = useAccount()
const backend = useBackend()
const [ready, setReady] = useState(false)
const [impersonating, setImpersonating] = useState(false)
const [error, setError] = useState(false)
const [refreshCount, setRefreshCount] = useState(0)
/*
* Avoid hydration errors
*/
useEffect(() => {
if (admin?.account?.username && account?.username && !impersonating.admin)
setImpersonating({
admin: admin.account.username,
user: account.username,
})
}, [admin])
useEffect(() => {
const verifyUser = async () => {
if (!error) {
const [status, data] = await backend.ping()
if (status === 200 && data.result === 'success') {
// Refresh account in local storage
setAccount({
...account,
...data.account,
bestBefore: Date.now() + 3600000,
})
} else if (status === 451) setError('consentLacking')
else {
if (data?.error?.error) setError(data.error.error)
else signOut()
}
setReady(true)
}
}
// Don't hammer the backend. Check once per hour.
if (token && !error && (!account.bestBefore || account.bestBefore < Date.now())) verifyUser()
setReady(true)
}, [admin, refreshCount, signOut])
const refresh = () => {
setRefreshCount(refreshCount + 1)
setError(false)
}
if (!ready)
const banner = impersonating ? (
Hi {impersonating.admin}, you are currently impersonating {impersonating.user}
) : null
const childProps = { banner }
if (!token || !account.username) return
if (error) {
if (error === 'accountInactive') return
if (error === 'accountDisabled') return
if (error === 'accountBlocked') return
if (error === 'consentLacking') return
return
}
if (!roles.levels[account.role] || roles.levels[account.role] < roles.levels[requiredRole]) {
return
}
return children
}
/**
* A component to display different content to users or visitors.
*
* This is a convenience component to not have to check
* for a user account is many different places.
*
* @component
* @param {object} props - All component props
* @param {JSX.Element} userContent - The content to show to users
* @param {JSX.Element} visitorContent - The content to show to visitors (not-logged in)
* @returns {JSX.Element}
*/
export const UserVisitorContent = ({ userContent = null, visitorContent = null }) => {
const { account, setAccount, token } = useAccount()
const backend = useBackend()
const [ready, setReady] = useState(false)
const [error, setError] = useState(false)
/*
* Avoid hydration errors
*/
useEffect(() => {
const verifyUser = async () => {
const [status, data] = await backend.ping()
if (status === 200 && data.result === 'success') {
// Refresh account in local storage
setAccount({
...account,
...data.account,
bestBefore: Date.now() + 3600000,
})
} else {
if (data?.error?.error) setError(data.error.error)
}
setReady(true)
}
if (token) {
// Don't hammer the backend. Check once per hour.
if (!account.bestBefore || account.bestBefore < Date.now()) verifyUser()
}
setReady(true)
}, [])
if (!ready) return
if (error)
return (
This is unexpected. You may want to report this.
)
return token && account.username ? userContent : visitorContent
}