Skip to content

GenieFramework/StippleUsers.jl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

StippleUsers

A middle layer to provide consistent user authorisation independent of the methods of authentication and authorisation.

The package exports:

  • default_user() - the default username, if only a single user is required (mainly used to keep the app functional without any specialisation)
  • default_role() - the default role that is attributed to each user, default: user
  • get_user() - obtain the current user, needs to be specialised (can be any type), default: default_user()
  • get_roles() - obtain the roles of the current user, needs to be specialised, default: user !== nothing ? [default_role(App)] : String[]
  • is_authorised(; role = default_role()) - return whether the current user has the role or any of the roles defined by the role keyword, can be specialised

Customization is typically done by specialising get_user() and get_roles(), it is also possible to specialise is_authorised() but not recommended. As the middle layer is designed to allow for app-dependent authorisation, specialisation needs provide the app type it is meant to work with, e.g.

with GenieAuthentication

using GenieAuthentication
StippleUsers.get_user(::AllApps) = get_authentication()

to provide the user id of GenieAuthentication for all apps. Note that const AllApps = Typ{<:ReactiveModel} has been defined for convenience.

with Snowpark Container Services

StippleUsers.get_user(::Type{SnowApp}) = get(headers(), "sf-context-current-user", "not_authorised")
StippleUsers.get_roles(::Type{SnowApp}, user::String) = user == "not_authorised" ? String[] : [default_role()]

to provide the Snowpark user for the (explicit) app SnowApp

Example 1 - Numbered Users and Admins for a all Apps

using Stipple, Stipple.ReactiveTools, StippleUsers

@app MyApp begin
    @in x = 1
end

# define roles as the first part of the string
StippleUsers.get_roles(::AllApps, user::String) = String[split(user, '_')[1]]

# case 1: normal user
StippleUsers.get_user(::AllApps) = "user_1"

get_roles()
# ["user"]

is_authorised()
# true

is_authorised(role = "admin")
# false

# case 2: Admin
StippleUsers.get_user(::AllApps) = "admin_1"

get_roles()
# ["admin"]

is_authorised()
# false

is_authorised(role = "admin")
# true

Example 2 - User List via Roles for a single App

using Stipple, Stipple.ReactiveTools, StippleUsers

@app MyApp begin
    @in x = 1
end

# make roles identical to user
StippleUsers.get_roles(::Type{MyApp}, user::String) = [user]

# case 1: normal user
StippleUsers.get_user(::Type{MyApp}) = "user_1"

get_roles(MyApp)
# ["user_1"]

is_authorised(MyApp)
# false

userlist() = ["user_1", "admin_1"]
is_authorised(MyApp, role = userlist())
# true

# case 2: Admin
StippleUsers.get_user(::Type{MyApp}) = "admin_1"

get_roles(MyApp)
# ["admin_1"]

is_authorised(MyApp, role = userlist())
# true

Example 3 - Overwriting is_authorised() for a specific implicit model

using Stipple, Stipple.ReactiveTools, StippleUsers

# define an implicit model
@app begin
    @in x = 1
end

userlist() = ["user_1", "admin_1"]

# define `App` as the module's implicit model
App = Stipple.@type

# define `is_authorised()` for the implicit App
# Note that it is important to allow for kwargs, because internal handling will call `is_authorised()` with the `role` kwarg.
StippleUsers.is_authorised(::Type{App}, user::String; kwargs...) = user  userlist()

StippleUsers.get_user(::Type{App}) = "user_1"
is_authorised(App)
# true

StippleUsers.get_user(::Type{App}) = "user_2"
is_authorised(App)
# false

StippleUsers.get_user(::Type{App}) = "admin_1"
is_authorised(App)
# true

Example 4 - applying authorisation to a Genie web application

using Stipple, Stipple.ReactiveTools, StippleUsers

@app MyApp begin
    @in x = 1
end

# create a random user or admin
StippleUsers.get_user(::Type{MyApp}) = "$(rand(("user", "admin")))_$(rand(1:100))"

# define the role as first part of the string
StippleUsers.get_roles(::Type{MyApp}, user::String) = String[split(user, '_')[1]]

# define an admin check which returns nothing in case of success and a not-found-page in case of failure
admin_check() = is_authorised(MyApp, role = "admin") ? nothing : not_found()

ui() = "Hello Admin!"
@page("/", ui, model = MyApp, pre = admin_check)

up(open_browser = true)
# reload the page several times; depending on whether you are a (random) admin, the page will be shown or not

About

middle layer for user authorisation

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages