Skip to content

Instantly share code, notes, and snippets.

@GaZaTu
Last active August 5, 2019 18:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save GaZaTu/d26606ef22eeffe8e506fafce7ab10ad to your computer and use it in GitHub Desktop.
Save GaZaTu/d26606ef22eeffe8e506fafce7ab10ad to your computer and use it in GitHub Desktop.
import * as React from 'react';
import Axios, { AxiosInstance } from 'axios';
import { createContext, consume } from '../lib/context-utils';
import { AuthContext } from './AuthProvider';
export const ApiContext = createContext('apiContext', {
api: undefined as AxiosInstance | undefined,
auth: undefined as React.ContextType<typeof AuthContext> | undefined,
})
interface Props {
[AuthContext.displayName]: React.ContextType<typeof AuthContext>
children?: React.ReactNode
}
interface State {
}
class ApiProvider extends React.PureComponent<Props, State> {
render() {
return (
<ApiContext.Provider value={this.api}>
{this.props.children}
</ApiContext.Provider>
)
}
makeApi() {
return Axios.create({
baseURL: process.env.REACT_APP_API_ENDPOINT!,
headers: {
common: {
'Content-Type': 'application/json',
'Authorization': this.auth.data && `Bearer ${this.auth.data.token}`,
},
},
})
}
get auth() {
return this.props[AuthContext.displayName]
}
get api() {
return {
api: this.makeApi(),
auth: this.auth,
}
}
}
export default consume(AuthContext)(ApiProvider)
import * as React from 'react';
import { createContext } from '../lib/context-utils';
interface User {
_id: string
permissions: string[]
}
interface AuthData {
token: string
info: User
}
export const AuthContext = createContext('authContext', {
data: undefined as AuthData | undefined,
login: (() => { }) as (data: AuthData) => void,
logout: (() => { }) as () => void,
isAuthorized: (() => false) as (...roles: string[]) => boolean,
ensureAuthorized: (() => { }) as (...roles: string[]) => void,
})
interface Props {
children?: React.ReactNode
}
interface State {
data: AuthData | undefined
}
class AuthProvider extends React.PureComponent<Props, State> {
readonly state: State = {
data: undefined,
}
login = (data: AuthData) => {
this.setState({ data })
}
logout = () => {
this.setState({ data: undefined })
}
isAuthorized = (...roles: string[]) => {
function arrayIncludesAll<T>(array: T[], includes: T[]) {
for (const needed of includes) {
if (!array.includes(needed)) {
return false
}
}
return true
}
if (this.state.data) {
return arrayIncludesAll(this.state.data.info.permissions || [], roles)
} else {
return false
}
}
ensureAuthorized = (...roles: string[]) => {
if (!this.isAuthorized(...roles)) {
throw new Error('Unauthorized')
}
}
render() {
return (
<AuthContext.Provider value={this.auth}>
{this.props.children}
</AuthContext.Provider>
)
}
get auth() {
return {
data: this.state.data,
login: this.login,
logout: this.logout,
isAuthorized: this.isAuthorized,
ensureAuthorized: this.ensureAuthorized,
}
}
}
export default AuthProvider
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment