(use-modules (goblins) (goblins actor-lib methods) (ice-9 match) (srfi srfi-9) (srfi srfi-9 gnu)) (define-record-type ; : name of the type (make-pos x y ); make-pos: constructor, takes two arguments pos? ; pos?: brand-check predicate (is it a pos?) (x pos-x ); pos-x: accessor for x (y pos-y )); pos-y: accessor for y ;; Make a sealer, unsealer, and brand-check predicate using ;; dynamic type generation. (define (make-sealer-triplet) (define-record-type (seal val ); constructor (sealer) sealed? ; predicate (brand-check) (val unseal )); accessor (unsealer) ;; Prevents snooping on contents at REPL, etc (define (print-seal _rec port) (display "#" port)) (set-record-type-printer! print-seal) ;; Return sealer, unsealer, sealed? predicate (values seal unseal sealed?)) (define* (spawn-post-and-editor-internal blog-sealer #:key title author body) ;; The public blogpost (define (^post _bcom) (methods ((get-content) (cons '*post* ($ editor 'get-data))) ;; *New*: get a sealed version of the editor from anywhere ((get-sealed-editor) (blog-sealer (list '*editor* editor))) ;; *New*: get a sealed version of self for self-attestation ((get-sealed-self) (blog-sealer (list '*post-self-proof* post))))) ;; The editing interface (define (^editor bcom title author body) (methods ((update #:key (title title) (author author) (body body)) (bcom (^editor bcom title author body))) ((get-data) (list title author body)))) ;; spawn and return the post and editor (define post (spawn ^post)) (define editor (spawn ^editor title author body)) (values post editor)) (define (new-spawn-blog-and-admin title) ;; New: sealers / unsealers relevant to this blog (define-values (blog-seal blog-unseal blog-sealed?) (make-sealer-triplet)) (define posts (spawn ^cell '())) (define (^blog _bcom) (methods ((get-title) (title)) ((get-posts) ($ posts 'get)))) (define (^admin bcom) (methods ;; *New:* A method to create posts specifically for this blog ((new-post-and-editor #:key title author body) (define-values (post editor) (spawn-post-and-editor-internal blog-seal #:title title #:author author #:body body)) (list post editor)) ;; *Updated:* check that a post was made (and is updateable) ;; by this blog ((add-post post) ;; (This part is the same as in the last version) (define current-posts ($ posts 'get)) (define new-posts (cons post current-posts)) ;; *New*: Ensure this is a post from this blog ;; This is accomplished by asking the post to provide the sealed ;; version "of itself". The `blog-unseal` method will throw an error ;; if it is sealed by anything other than `blog-seal (define post-self-proof ($ post 'get-sealed-self)) (match (blog-unseal post-self-proof) (('*post-self-proof* obj) ; match against tagged proof (unless (eq? obj post ); equality check: same object? (error "Self-proof not for this post")))) ;; Checks out, let's update the set of posts ($ posts 'set new-posts)) ;; *New:* A method to edit any post associated with this blog ((edit-post post #:rest args) (define sealed-editor ($ post 'get-sealed-editor)) (define editor (match (blog-unseal sealed-editor) (('*editor* editor) ; match against tagged editor (return editor)))) (apply $ editor 'update args)))) (values (spawn ^blog) (spawn ^admin)))