Table of Contents
Basolato check whether value is valid in middleware. checkCsrfToken()
and checkAuthToken()
are available.
These procs return Check
object. catch()
defines what to do if value is invalid.
Basolato can check whether csrf token is valid if request metod is post
, put
, patch
, delete
.
When you use SCF,Set ${csrfToken()}
in view.
#? stdtmpl | standard
#import basolato/view
#proc createHtml*():string =
<form method="post">
${csrfToken()}
.
.
</form>
When you use Karax, Set csrfTokenKarax()
in view.
import karax / [karaxdsl, vdom]
import basolato/view
proc createHtml*():string =
var vnode = buildHtml(tdiv):
form(`method`="post"):
csrfTokenKarax()
.
.
If checkCsrfToken(request)
is in template framework()
, csrf check is available.
middleware/framework_middleware.nim
template framework*() =
checkCsrfToken(request).catch()
If token is invalid, return 500
.
You can overwrite your own custom error handring.
# If you want to return 403
checkCsrfToken(request).catch(Error403, "Error message")
# If you want to redirect login page
checkCsrfToken(request).catch(Error302, "/login")
type
CookieData* = ref object
name: string
value: string
expire: string
sameSite: SameSite
secure: bool
httpOnly: bool
domain: string
path: string
Cookie* = ref object
request: Request
cookies*: seq[CookieData]
proc newCookie*(request:Request):Cookie =
proc get*(this:Cookie, name:string):string =
proc set*(this:var Cookie, name, value: string, expire:DateTime,
sameSite: SameSite=Lax, secure = false, httpOnly = false, domain = "",
path = "/") =
proc set*(this:var Cookie, name, value: string, sameSite: SameSite=Lax,
secure = false, httpOnly = false, domain = "", path = "/") =
proc updateExpire*(this:var Cookie, name:string, days:int, path="/") =
proc delete*(this:Cookie, key:string, path="/"):Cookie =
proc destroy*(this:Cookie, path="/"):Cookie =
proc setCookie*(response:Response, cookie:Cookie):Response =
get cookie
proc index(this:Controller): Response =
let val = newCookie(this.request).get("key")
set cookie
proc store*(this:Controller): Response =
let name = this.request.params["name"]
var cookie = newCookie(this.request)
cookie.set("name", name)
return render("with cookie").setCookie(cookie)
update cookie expire
proc store*(this:Controller): Response =
var cookie = newCookie(this.request)
cookie.updateExpire("name", 5)
# cookie will be deleted after 5 days from now
return render("with cookie").setCookie(cookie)
delete cookie
proc index(this:Controller): Response =
var cookie = newCookie(this.request)
cookie.delete("key")
return render("with cookie").setCookie(cookie)
destroy all cookies
proc index(this:Controller): Response =
var cookie = newCookie(this.request)
cookie.destroy()
return render("with cookie").setCookie(cookie)
Secure
and HttpOnly
in production environment, they will not be read by JavaScript and can only be used in HTTPS.
Basolato use nimAES as session DB. We have a plan to be able to choose Redis in the future.
If you set sessionId
in arg of newSession()
, it return existing session otherwise create new session.
type
SessionType* = enum
File
Redis # Not work now
Session* = ref object
db: SessionDb
proc newSession*(token="", typ:SessionType=File):Session =
# If you set valid token, it connect to existing session.
# If you don't set token, it creates new session.
proc getToken*(this:Session):string =
proc set*(this:Session, key, value:string):Session =
proc some*(this:SessionDb, key:string):bool =
proc get*(this:Session, key:string):string =
proc delete*(this:Session, key:string): Session =
proc destroy*(this:Session) =
get session id
proc index(this:Controller): Response =
let sessionId = newSession().getToken()
set value in session
proc store(this:Controller): Response =
let key = this.request.params["key"]
let value = this.request.params["value"]
discard newSession().set(key, value)
check and get value in session
proc index(this:Controller): Response =
let sessionId = newCookie(this.request).get("session_id")
let key = this.request.params["key"]
let session = newSession(sessionId)
var value:string
if session.some(key):
value = session.get(key)
delete one key-value pair of session
proc destroy(this:Controller): Response =
let sessionId = newCookie(this.request).getToken()
let key = this.request.params["key"]
discard newSession(sessionId).delete(key)
destroy session
proc destroy(this:Controller): Response =
let sessionId = newCookie(this.request).getToken()
newSession(sessionId).destroy()
Basolato has Auth system. it conceal inconvenient cookie and session process.
type Auth* = ref object
isLogin*:bool
session*:Session
proc newAuth*(request:Request):Auth =
proc newAuth*():Auth =
proc login*(this:Auth) =
proc logout*(this:Auth) =
proc isLogin*(this:Auth):bool =
proc getToken*(this:Auth):string =
proc set*(this:Auth, key, value:string):Auth =
proc some*(this:Auth, key:string):bool =
proc get*(this:Auth, key:string):string =
proc delete*(this:Auth, key:string):AUth =
proc setAuth*(response:Response, auth:Auth):Response =
# If not logged in, do nothing.
# If logged in but not updated any session value,
# expire of session_id is updated.
proc destroyAuth*(response:Response, auth:Auth):Response =
proc setFlash*(this:Auth, key, value:string) =
proc getFlash*(this:Auth):JsonNode =
login
proc index(this:Controller): Response =
let email = params["email"]
let password = params["password"]
let userId = newLoginUsecase().login(email, password)
this.auth.login()
this.auth.set("id", $userId)
return redirect("/").setAuth(auth)
logout
proc index(this:Controller): Response =
if this.auth.isLogin():
this.auth.logout()
redirect("/")
get auth
proc index(this:Controller): Response =
let loginName = this.auth.get("login_name")
set value in auth
proc index(this:Controller): Response =
let name = this.request.params["name"]
let auth = this.auth.set("login_name", name)
return render("auth").setAuth(auth)
check and get value in auth
proc index(this:Controller): Response =
var loginName:string
if this.auth.some("login_name"):
loginName = this.auth.get("login_name")
delete one key-value pair of session
proc destroy(this:Controller): Response =
this.auth.delete("login_name")
return render("auth").setAuth(auth)
destroy auth
proc destroy(this:Controller): Response =
return render("auth").destroyAuth(this.auth)
set flash message
proc store*(this:Controller):Response =
this.auth.setFlash("success", "Welcome to the Sample App!")
return redirect("/auth").setAuth(auth)
get flash message
proc show*(this:Controller):Response =
let flash = this.auth.getFlash()
return render(showHtml(user, flash=flash))