typealias Username = String
typealias Password = String
external interface AuthInProps : Props {
var signIn: (Username, Password) -> Unit
}
external interface AuthOutProps : Props {
var user: User
var signOff: () -> Unit
}
val CAuthIn = FC<AuthInProps>("Auth") { props ->
var name by useState("")
var pass by useState("")
span { +"Name: "
input { type = InputType.text
value = name
onChange = { name = it.target.value }}}
span { +"Pass: "
input { type = InputType.text
value = pass
onChange = { pass = it.target.value }}}
button { +"SignIn"
onClick = { props.signIn(name, pass) }}}
val CAuthOut = FC<AuthOutProps>("Auth") { props ->
div {
+props.user.username
button {
+"SignOut"
onClick = {
props.signOff()
}
}
}
}
external interface AuthContainerProps : Props {
var user: User?
var signIn: (Pair<User, Token>) -> Unit
var signOff: () -> Unit
}
val CAuthContainer = FC<AuthContainerProps>("AuthContainer")
{ props ->
val _user = props.user
if (_user != null) {
CAuthOut {
user = _user
signOff = props.signOff
}
} else {
CAuthIn {
signIn = { name: Username, pass: Password ->
val user = User(name, pass)
fetch( Config.loginPath,
jso { method = "POST"
headers = json(
"Content-Type" to "application/json")
body = user.json
}
)
.then { it.text() }
.then { props.signIn(
user to Json.decodeFromString<Token>(it)
)}}}
fun ChildrenBuilder.authProvider(
block: ChildrenBuilder.() -> Unit) =
child( FC<PropsWithChildren>("AuthProvider") {
var userInfo by useState<UserInfo>(null)
CAuthContainer {
user = userInfo?.first
signOff = { userInfo = null }
signIn = { userInfo = it }}
if (userInfo == null)
h1 { +"Authentication is required" }
else
userInfoContext.Provider(userInfo) {
block()}
}.create())
val userInfo = useContext(userInfoContext)
...
fetch( "url",
jso {
method = "POST"
headers = json(
"Content-Type" to "application/json",
"Authorization" to userInfo?.second?.authHeader
)
body = ...
)