RESTrict Framework#
The RESTrict Framework is a different way to think about constructing Web applications. It defines a new paradigm, functional-declarative hybrid, resource-oriented development, a hybrid of declarative and functional programming. It is the hope that this new paradigm engenders a new mental model for Web applications, one that more naturally fits the hypertext as the engine of application state.
The blog example#
The “Hello, World!” of applications is a simple blogging site. Making this application with the RESTrict Framework takes three steps.
1. Declare the resources#
To declare your resources, you define .resource
or .resources
files that
contain the shape of the data for your resources, how they relate to one
another, and who can access the different actions on the resources.
Danger
Code subject to change The RESTrict Framework is currently in its early design and development phase. The following code sample is subject to change at any time.
refer to <security/auth/starlette> as saa
refer to <security/auth/password> as sap
use <types/scalar>
use <types/text>
use <types/time>
override saa.StarletteAuthentication {
dnc {
<party:1> principal: Person
}
}
party Person {
name: Text(1,100)
email: unique sap.Email
is_admin: boolean
password: hidden sap.Password
security {
mutators {
create: request.actor.is_authenticated |> not() |> or(request.actor.is_admin)
*: request.actor |> eq(self) |> or(request.actor.is_admin)
}
accessors {
<entrypoint> list: request.actor.is_admin
details: {
name: true
*: request.actor |> eq(self) |> or(request.actor.is_admin)
}
}
}
}
role Writer {
author: assignment.person
active: now |> gte(assignment.assigned) |> lte(assignment.unassigned)
dnc {
<previous:1> assignment: WriterAssignment
}
security {
mutators {
*: request.actor.is_admin
}
accessors {
<entrypoint> list: request.actor.is_admin
details: request.actor.is_admin
}
}
}
interval WriterAssignment {
assigned: Timestamp
unassigned: optional Timestamp : value |> gte(assigned)
dnc {
<party:1> person: Person
<next:1> writer: Writer
}
effects {
create {
assigned: now
writer: transact create Writer { assignment: self }
}
}
security {
mutators {
*: request.actor.is_admin
}
accessors {
*: request.actor.is_admin
}
}
}
moment Post {
title: Text(1,100)
published: optional Timestamp
content: Markdown
dnc {
<role:1> writer: Writer
<next:*> comments: page Comment
}
security {
mutators {
create: request.actor.roles |> filter(x | x is Writer) |> any(x | x.active)
modify: request.actor = writer.author
delete: request.actor = writer.author
}
accessors {
<entrypoint> list: now |> lte(published) |> or(reqeust.actor.is_admin)
details: published |> gte(now) |> or(request.actor.is_admin)
}
}
}
moment Comment {
author: readonly optional Person
submitted: readonly Timestamp
content: readonly Markdown(p, ul, ol, li)
dnc {
<party:1> author: optional Person
<previous:1> post: Post
}
effects {
create {
author: request.actor
submitted: now
content: request.body.content
}
}
security {
accessors {
details: {
author: request.actor.is_authenticated
}
}
mutators {
delete: request.actor |> in([author, post.author])
modify: request.actor = author
create: true
}
}
}
2. Start the application#
Install and run the application using Python 3.11 or newer.
pip install --user restrict-framework
python -m restrict --root post.resources
3. Use the API#
Use REST, GraphQL, and WebSockets to interact with the API.