A Simple Blog

A Simple Blog#

The “Hello, World!” of applications is a simple blogging site. Making this application with the RESTrict Framework takes three steps.

Listing 3 post.resources#
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
    }
  }
}