advancing declarative programming
play

Advancing Declarative Programming Aleksandar Milicevic - PowerPoint PPT Presentation

Advancing Declarative Programming Aleksandar Milicevic Massachusetts Institute of Technology May 07, 2015 1 What is Declarative Programming? 2 What is Declarative Programming? say what , not how describe what the program is intended to do in


  1. Solving maxClique Vs. Program Synthesis program synthesis maxClique find some program AST s.t., find some set of nodes s.t., it is a clique and for all possible values of its inputs for all possible other sets of nodes its specification holds not one is a larger clique some program: ASTNode | some clq: set Node | all env: Var -> Val | clique[clq] and spec[program, env] all ns: set Node | not (clique[ns] and #ns > #clq) similarities : the same some / all ( ∃∀ ) pattern the all quantifier is higher-order 8

  2. Solving maxClique Vs. Program Synthesis program synthesis maxClique find some program AST s.t., find some set of nodes s.t., it is a clique and for all possible values of its inputs for all possible other sets of nodes its specification holds not one is a larger clique some program: ASTNode | some clq: set Node | all env: Var -> Val | clique[clq] and spec[program, env] all ns: set Node | not (clique[ns] and #ns > #clq) similarities : the same some / all ( ∃∀ ) pattern the all quantifier is higher-order how do existing program synthesizers work? 8

  3. CEGIS : A Common Approach for Program Synthesis original synthesis formulation run { some prog: ASTNode | all env: Var -> Val | spec[prog, env] } [Solar-Lezama, ASPLOS’06] Counter-Example Guided Inductive Synthesis 9

  4. CEGIS : A Common Approach for Program Synthesis original synthesis formulation run { some prog: ASTNode | all env: Var -> Val | spec[prog, env] } [Solar-Lezama, ASPLOS’06] Counter-Example Guided Inductive Synthesis 1. search: find some program and some environment s.t. the spec holds, i.e., run { some prog: ASTNode | some env: Var -> Val | spec[prog, env] } to get a concrete candidate program $prog 9

  5. CEGIS : A Common Approach for Program Synthesis original synthesis formulation run { some prog: ASTNode | all env: Var -> Val | spec[prog, env] } [Solar-Lezama, ASPLOS’06] Counter-Example Guided Inductive Synthesis 1. search: find some program and some environment s.t. the spec holds, i.e., run { some prog: ASTNode | some env: Var -> Val | spec[prog, env] } to get a concrete candidate program $prog 2. verification: check if $prog holds for all possible environments: check { all env: Var -> Val | spec[$prog, env] } Done if verified; else, a concrete counterexample $env is returned as witness. 9

  6. CEGIS : A Common Approach for Program Synthesis original synthesis formulation run { some prog: ASTNode | all env: Var -> Val | spec[prog, env] } [Solar-Lezama, ASPLOS’06] Counter-Example Guided Inductive Synthesis 1. search: find some program and some environment s.t. the spec holds, i.e., run { some prog: ASTNode | some env: Var -> Val | spec[prog, env] } to get a concrete candidate program $prog 2. verification: check if $prog holds for all possible environments: check { all env: Var -> Val | spec[$prog, env] } Done if verified; else, a concrete counterexample $env is returned as witness. 3. induction: incrementally find a new program that additionally satisfies $env : run { some prog: ASTNode | some env: Var -> Val | spec[prog, env] and spec[prog, $env]} If UNSAT, return no solution; else, go to 2. 9

  7. A LLOY ∗ A LLOY ∗ key insight CEGIS can be applied to solve arbitrary higher-order formulas 10

  8. A LLOY ∗ generality solve arbitrary higher-order formulas no domain-specific knowledge needed 10

  9. A LLOY ∗ generality solve arbitrary higher-order formulas no domain-specific knowledge needed implementability key solver features for efficient implementation: – partial instances – incremental solving 10

  10. A LLOY ∗ generality solve arbitrary higher-order formulas no domain-specific knowledge needed implementability key solver features for efficient implementation: – partial instances – incremental solving wide applicability (in contrast to specialized synthesizers) program synthesis: SyGuS benchmarks security policy synthesis: Margrave solving graph problems: max-cut , max-clique , min-vertex-cover bounded verification: Turán’s theorem 10

  11. Generality : Nested Higher-Order Quantifiers fun keysum[nodes: set Node]: Int { sum n: nodes | n.key } pred maxMaxClique[edges: Node->Node, clq: set Node] { maxClique[edges, clq] all ns: set Node | not (maxClique[edges,clq2] and keysum[ns] > keysum[clq]) } run maxMaxClique for 5 n1 $clq key: 5 edges n2 n3 key: 0 key: 6 n4 key: 1 11

  12. Semantics : General Idea CEGIS: defined only for a single idiom (the ∃∀ formula pattern) 12

  13. Semantics : General Idea CEGIS: defined only for a single idiom (the ∃∀ formula pattern) A LLOY ∗ : generalized to arbitrary formulas 12

  14. Semantics : General Idea CEGIS: defined only for a single idiom (the ∃∀ formula pattern) A LLOY ∗ : generalized to arbitrary formulas 1. perform standard transformation: NNF and skolemization 12

  15. Semantics : General Idea CEGIS: defined only for a single idiom (the ∃∀ formula pattern) A LLOY ∗ : generalized to arbitrary formulas 1. perform standard transformation: NNF and skolemization 2. decompose arbitrary formula into known idioms → FOL : first-order formula : disjunction → OR A : higher-order top-level ∀ quantifier (not skolemizable) → E 12

  16. Semantics : General Idea CEGIS: defined only for a single idiom (the ∃∀ formula pattern) A LLOY ∗ : generalized to arbitrary formulas 1. perform standard transformation: NNF and skolemization 2. decompose arbitrary formula into known idioms → FOL : first-order formula : disjunction → OR A : higher-order top-level ∀ quantifier (not skolemizable) → E 3. solve using the following decision procedure → FOL : solve directly with Kodkod (first-order relational solver) : solve each disjunct separately → OR A : apply CEGIS → E 12

  17. A LLOY ∗ Implementation Caveats some prog: Node | A ( conj : E $prog in Node and acyclic[$prog], acyclic[prog] → eQuant : some eval ..., all eval: Node -> ( Int +Bool) | semantics[eval] implies spec[prog, eval] aQuant : all eval ...) 13

  18. A LLOY ∗ Implementation Caveats some prog: Node | A ( conj : E $prog in Node and acyclic[$prog], acyclic[prog] → eQuant : some eval ..., all eval: Node -> ( Int +Bool) | semantics[eval] implies spec[prog, eval] aQuant : all eval ...) 1. candidate search solve conj ∧ eQuant → candidate instance $cand : values of all relations except eQuant . var 13

  19. A LLOY ∗ Implementation Caveats some prog: Node | A ( conj : E $prog in Node and acyclic[$prog], acyclic[prog] → eQuant : some eval ..., all eval: Node -> ( Int +Bool) | semantics[eval] implies spec[prog, eval] aQuant : all eval ...) 1. candidate search solve conj ∧ eQuant → candidate instance $cand : values of all relations except eQuant . var 2. verification solve ¬ aQuant against the $cand partial instance → counterexample $cex : value of the eQuant . var relation 13

  20. A LLOY ∗ Implementation Caveats some prog: Node | A ( conj : E $prog in Node and acyclic[$prog], acyclic[prog] → eQuant : some eval ..., all eval: Node -> ( Int +Bool) | semantics[eval] implies spec[prog, eval] aQuant : all eval ...) 1. candidate search solve conj ∧ eQuant → candidate instance $cand : values of all relations except eQuant . var 2. verification solve ¬ aQuant against the $cand partial instance partial instance → counterexample $cex : value of the eQuant . var relation • partial solution known upfront • enforced using bounds 13

  21. A LLOY ∗ Implementation Caveats some prog: Node | A ( conj : E $prog in Node and acyclic[$prog], acyclic[prog] → eQuant : some eval ..., all eval: Node -> ( Int +Bool) | semantics[eval] implies spec[prog, eval] aQuant : all eval ...) 1. candidate search solve conj ∧ eQuant → candidate instance $cand : values of all relations except eQuant . var 2. verification solve ¬ aQuant against the $cand partial instance partial instance → counterexample $cex : value of the eQuant . var relation • partial solution known upfront • enforced using bounds 3. induction use incremental solving to add replace eQuant . var with $cex in eQuant . body to previous search condition 13

  22. A LLOY ∗ Implementation Caveats some prog: Node | A ( conj : E $prog in Node and acyclic[$prog], acyclic[prog] → eQuant : some eval ..., all eval: Node -> ( Int +Bool) | semantics[eval] implies spec[prog, eval] aQuant : all eval ...) 1. candidate search solve conj ∧ eQuant → candidate instance $cand : values of all relations except eQuant . var 2. verification solve ¬ aQuant against the $cand partial instance partial instance → counterexample $cex : value of the eQuant . var relation • partial solution known upfront • enforced using bounds 3. induction use incremental solving to add incremental solving replace eQuant . var with $cex in eQuant . body • continue from prev solver instance • the solver reuses learned clauses to previous search condition 13

  23. A LLOY ∗ Implementation Caveats some prog: Node | A ( conj : E $prog in Node and acyclic[$prog], acyclic[prog] → eQuant : some eval ..., all eval: Node -> ( Int +Bool) | semantics[eval] implies spec[prog, eval] aQuant : all eval ...) 1. candidate search solve conj ∧ eQuant → candidate instance $cand : values of all relations except eQuant . var 2. verification solve ¬ aQuant against the $cand partial instance partial instance → counterexample $cex : value of the eQuant . var relation • partial solution known upfront • enforced using bounds 3. induction use incremental solving to add incremental solving replace eQuant . var with $cex in eQuant . body • continue from prev solver instance • the solver reuses learned clauses to previous search condition ? what if the increment formula is not first-order – optimization 1: use its weaker “first-order version” 13

  24. A LLOY ∗ Optimization 2. domain constraints “for all possible eval , “for all eval that satisfy the semantics, vs. if the semantics hold then the spec the spec must hold” must hold” 14

  25. A LLOY ∗ Optimization 2. domain constraints “for all possible eval , “for all eval that satisfy the semantics, vs. if the semantics hold then the spec the spec must hold” must hold” logically equivalent, but , when “for” implemented as CEGIS: 14

  26. A LLOY ∗ Optimization 2. domain constraints “for all possible eval , “for all eval that satisfy the semantics, vs. if the semantics hold then the spec the spec must hold” must hold” logically equivalent, but , when “for” implemented as CEGIS: pred synth[prog: Node] { all eval: Node -> ( Int +Bool) | semantics[eval] implies spec[prog, eval] } → candidate search some prog: Node | some eval: Node -> ( Int +Bool) | semantics[eval] implies spec[prog, eval] → a valid candidate doesn’t have to satisfy the semantics predicate! ✗ 14

  27. A LLOY ∗ Optimization 2. domain constraints “for all possible eval , “for all eval that satisfy the semantics, vs. if the semantics hold then the spec the spec must hold” must hold” logically equivalent, but , when “for” implemented as CEGIS: pred synth[prog: Node] { pred synth[prog: Node] { all eval: Node -> ( Int +Bool) | all eval: Node -> ( Int +Bool) when semantics[eval] semantics[eval] implies spec[prog, eval] spec[prog, eval] } } → → candidate search candidate search some prog: Node | some prog: Node | some eval: Node -> ( Int +Bool) | some eval: Node -> ( Int +Bool) when semantics[eval] | semantics[eval] implies spec[prog, eval] spec[prog, eval] → → a valid candidate doesn’t have to a valid candidate must satisfy the satisfy the semantics predicate! semantics predicate! ✗ ✔ 14

  28. A LLOY ∗ Evaluation evaluation goals 15

  29. A LLOY ∗ Evaluation evaluation goals 1. scalability on classical higher-order graph problems ? does A LLOY ∗ scale beyond “toy-sized” graphs 15

  30. A LLOY ∗ Evaluation evaluation goals 1. scalability on classical higher-order graph problems ? does A LLOY ∗ scale beyond “toy-sized” graphs 2. applicability to program synthesis ? expressiveness: how many SyGuS benchmarks can be written in A LLOY ∗ ? power: how many SyGuS benchmarks can be solved with A LLOY ∗ ? scalability: how does A LLOY ∗ compare to other synthesizers 15

  31. A LLOY ∗ Evaluation evaluation goals 1. scalability on classical higher-order graph problems ? does A LLOY ∗ scale beyond “toy-sized” graphs 2. applicability to program synthesis ? expressiveness: how many SyGuS benchmarks can be written in A LLOY ∗ ? power: how many SyGuS benchmarks can be solved with A LLOY ∗ ? scalability: how does A LLOY ∗ compare to other synthesizers 3. benefits of the two optimizations ? do A LLOY ∗ optimizations improve overall solving times 15

  32. Evaluation: Graph Algorithms 80 ¡ max clique 70 ¡ max cut 60 ¡ Solving Time (s) max indep. set 50 ¡ min vertex cover 40 ¡ 30 ¡ 20 ¡ 10 ¡ 0 ¡ 2 ¡ 3 ¡ 5 ¡ 7 ¡ 9 ¡ 13 ¡ 15 ¡ 20 ¡ 25 ¡ 30 ¡ 35 ¡ 40 ¡ 45 ¡ 50 ¡ # Nodes 16

  33. Evaluation: Program Synthesis expressiveness we extended Alloy to support bit vectors we encoded 123/173 benchmarks, i.e., all except “ICFP problems” – reason for skipping ICFP: 64-bit bit vectors (not supported by Kodkod) – (aside) not one of them was solved by any of the competition solvers power A LLOY ∗ was able to solve all different categories of benchmarks – integer benchmarks, bit vector benchmarks, let constructs, synthesizing multiple functions at once, multiple applications of the synthesized function scalability many of the 123 benchmarks are either too easy or too difficult → not suitable for scalability comparison we primarily used the integer benchmarks we also picked a few bit vector benchmarks that were too hard for all solvers 17

  34. Evaluation: Program Synthesis scalability comparison (integer benchmarks) 1000 Alloy* Enumerative Stochastic Symbolic Sketch 100 Solving Time (s) 10 1 0.1 0.01 max-2 max-3 max-4 max-5 array-2 array-3 array-4 array-5 18

  35. Evaluation: Program Synthesis scalability comparison (select bit vector benchmarks) benchmarks – parity-AIG-d1 : full parity circuit using AND and NOT gates – parity-NAND-d1 : full parity circuit using AND always followed by NOT 18

  36. Evaluation: Program Synthesis scalability comparison (select bit vector benchmarks) benchmarks – parity-AIG-d1 : full parity circuit using AND and NOT gates – parity-NAND-d1 : full parity circuit using AND always followed by NOT all solvers (including A LLOY ∗ ) time out on both (limit: 1000s) 18

  37. Evaluation: Program Synthesis scalability comparison (select bit vector benchmarks) benchmarks – parity-AIG-d1 : full parity circuit using AND and NOT gates – parity-NAND-d1 : full parity circuit using AND always followed by NOT all solvers (including A LLOY ∗ ) time out on both (limit: 1000s) custom tweaks in A LLOY ∗ synthesis models: – create and use a single type of gate – impose partial ordering between gates 18

  38. Evaluation: Program Synthesis scalability comparison (select bit vector benchmarks) benchmarks – parity-AIG-d1 : full parity circuit using AND and NOT gates – parity-NAND-d1 : full parity circuit using AND always followed by NOT all solvers (including A LLOY ∗ ) time out on both (limit: 1000s) custom tweaks in A LLOY ∗ synthesis models: – create and use a single type of gate – impose partial ordering between gates parity-AIG-d1 parity-NAND-d1 sig AIG extends BoolNode { sig NAND extends BoolNode { left, right: one BoolNode left, right: one BoolNode invLhs, invRhs, invOut: one Bool } } pred aig_semantics[eval: Node->( Int +Bool)] { pred nand_semantics[eval: Node->( Int +Bool)] { all n: AIG | all n: NAND | eval[n] = ((eval[n.left] ^ n.invLhs) && eval[n] = !(eval[n.left] && (eval[n.right] ^ n.invRhs) eval[n.right]) ) ^ n.invOut} } run synth for 0 but -1..0 Int , exactly 15 AIG run synth for 0 but -1..0 Int , exactly 23 NAND 18

  39. Evaluation: Program Synthesis scalability comparison (select bit vector benchmarks) benchmarks – parity-AIG-d1 : full parity circuit using AND and NOT gates – parity-NAND-d1 : full parity circuit using AND always followed by NOT all solvers (including A LLOY ∗ ) time out on both (limit: 1000s) custom tweaks in A LLOY ∗ synthesis models: – create and use a single type of gate – impose partial ordering between gates parity-AIG-d1 parity-NAND-d1 sig AIG extends BoolNode { sig NAND extends BoolNode { left, right: one BoolNode left, right: one BoolNode invLhs, invRhs, invOut: one Bool } } pred aig_semantics[eval: Node->( Int +Bool)] { pred nand_semantics[eval: Node->( Int +Bool)] { all n: AIG | all n: NAND | eval[n] = ((eval[n.left] ^ n.invLhs) && eval[n] = !(eval[n.left] && (eval[n.right] ^ n.invRhs) eval[n.right]) ) ^ n.invOut} } run synth for 0 but -1..0 Int , exactly 15 AIG run synth for 0 but -1..0 Int , exactly 23 NAND solving time w/ partial ordering: 20s solving time w/ partial ordering: 30s solving time w/o partial ordering: 80s solving time w/o partial ordering: ∞ 18

  40. Evaluation: Benefits of A LLOY ∗ Optimizations base w/ optimizations max2 0.4 s 0.3 s 7.6 s 0.9 s max3 t/o 1.5 s max4 max5 t/o 4.2 s t/o 16.3 s max6 t/o 163.6 s max7 max8 t/o 987.3 s 140.0 s 1.6 s array-search2 t/o 4.0 s array-search3 array-search4 t/o 16.1 s t/o 485.6 s array-search5 base w/ optimizations 3.5 s 0.5 s turan5 12.8 s 2.1 s turan6 turan7 235.0 s 3.8 s t/o 15.0 s turan8 t/o 45.0 s turan9 turan1 0 t/o 168.0 s 19

  41. A LLOY ∗ Conclusion A LLOY ∗ is general purpose constraint solver capable of efficiently solving arbitrary higher-order formulas sound & complete within given bounds 20

  42. A LLOY ∗ Conclusion A LLOY ∗ is general purpose constraint solver capable of efficiently solving arbitrary higher-order formulas sound & complete within given bounds higher-order and alloy historically bit-blasting higher-order quantifiers: attempted, deemed intractable previously many ad hoc mods to alloy – aluminum, razor, staged execution, ... 20

  43. A LLOY ∗ Conclusion A LLOY ∗ is general purpose constraint solver capable of efficiently solving arbitrary higher-order formulas sound & complete within given bounds higher-order and alloy historically bit-blasting higher-order quantifiers: attempted, deemed intractable previously many ad hoc mods to alloy – aluminum, razor, staged execution, ... why is this important? accessible to wider audience, encourages new applications potential impact – abundance of tools that build on Alloy/Kodkod, for testing, program analysis, security, bounded verification, executable specifications, ... 20

  44. S UNNY : Model-Based Reactive Web Framework (my previous work) executable program specs for java synthesis spec spec formal logic DSL engine sophisticated search engine translation/compilation apps apps complex algorithms, domain-specific uses constraint solving [ABZ’14] • unified specification & implementation language [Onward’13] [ABZ’12,SCP’14,ICSE’15] • model-based web framework • more powerful constraint solver • reactive, single-tier, policy-agnostic • capable of solving a whole new • what instead of how category of formal specifications 21

  45. A simple web app: S UNNY IRC custom-tailored internet chat relay app 22

  46. A simple web app: S UNNY IRC custom-tailored internet chat relay app 22

  47. A simple web app: S UNNY IRC custom-tailored internet chat relay app 22

  48. Conceptually simple, but in practice... 23

  49. Conceptually simple, but in practice... distributed system concurrency issues keeping everyone updated 23

  50. Conceptually simple, but in practice... distributed system concurrency issues keeping everyone updated heterogeneous environment rails + javascript + ajax + jquery + ... html + erb + css + sass + scss + bootstrap + ... db + schema + server config + routes + ... 23

  51. Conceptually simple, but in practice... distributed system concurrency issues keeping everyone updated heterogeneous environment rails + javascript + ajax + jquery + ... html + erb + css + sass + scss + bootstrap + ... db + schema + server config + routes + ... abstraction gap high-level problem domain low-level implementation level 23

  52. Conceptually simple, but in practice... distributed system concurrency issues keeping everyone updated heterogeneous environment rails + javascript + ajax + jquery + ... html + erb + css + sass + scss + bootstrap + ... db + schema + server config + routes + ... abstraction gap high-level problem domain low-level implementation level 23

  53. MDD : how far can it get us? exercise : sketch out a model (design, spec) for the Sunny IRC application 24

  54. Sunny IRC: data model user class User record class Msg record class ChatRoom # inherited: name, email: Text text: Text name: Text sender: User members: set User salute: () -> "Hi #{ this .name}" time: Val messages: compose set Msg record: automatically persisted objects with typed fields user: special kind of record, assumes certain fields, auth, etc. set: denotes non-scalar (set) type compose: denotes ownership, deletion propagation, etc. 25

  55. Sunny IRC: machine model client class Client server class Server user: User rooms: compose set ChatRoom client: special kind of record, used to represent client machines server: special kind of record, used to represent the server machine 26

  56. Sunny IRC: event model event class SendMsg from: client: Client to: server: Server params: room: ChatRoom msgText: Text requires: () -> return "must log in!" unless this .client ? .user return "must join room!" unless this .room ? .members. contains ( this .client.user) ensures: () -> this .room.messages.push Msg.create(sender: this .client.user text: this .msgText time: Date.now()) to, from: sender and receiver machines params: event parameters requires: event precondition ensures: event handler (postcondition) 27

  57. Modeling done. What next? challenge how to make the most of this model? 28

  58. Modeling done. What next? challenge how to make the most of this model? goal make the model executable as much as possible! 28

  59. Traditional MVC Approach 29

  60. Traditional MVC Approach boilerplate: write a matching DB schema turn each record into a resource (model class) turn each event into a controller and implement the CRUD operations configure URL routes for each resource 29

  61. Traditional MVC Approach boilerplate: write a matching DB schema turn each record into a resource (model class) turn each event into a controller and implement the CRUD operations configure URL routes for each resource aesthetics: design and implement a nice looking HTML/CSS presentation 29

  62. Traditional MVC Approach boilerplate: write a matching DB schema turn each record into a resource (model class) turn each event into a controller and implement the CRUD operations configure URL routes for each resource aesthetics: design and implement a nice looking HTML/CSS presentation to make it interactive: decide how to implement server push keep track of who’s viewing what monitor resource accesses push changes to clients when resources are modified implement client-side Javascript to accept pushed changes and dynamically update the DOM 29

  63. Traditional MVC Approach boilerplate: write a matching DB schema turn each record into a resource (model class) turn each event into a controller and implement the CRUD operations configure URL routes for each resource aesthetics: design and implement a nice looking HTML/CSS presentation to make it interactive: decide how to implement server push keep track of who’s viewing what monitor resource accesses push changes to clients when resources are modified implement client-side Javascript to accept pushed changes and dynamically update the DOM 29

  64. S UNNY demo demo : responsive GUI without messing with javascript 30

  65. GUIs in S UNNY : dynamic templates like standard templating engine with data bindings automatically re-rendered when the model changes 31

  66. GUIs in S UNNY : dynamic templates like standard templating engine with data bindings automatically re-rendered when the model changes online_users.html <div> {{ #each Server.onlineClients.user }} {{ > user_tpl user = this }} {{ /each }} </div> 31

  67. GUIs in S UNNY : binding to events 32

  68. GUIs in S UNNY : binding to events room_tpl.html <div {{ SendMsg room = this.room }} > <div> <input type="text" name="text" placeholder="Enter message" {{ SendMsg_msgText }} {{ sunny_trigger }} /> </div> <button {{ sunny_trigger }} >Send</button> </div> 32

  69. GUIs in S UNNY : binding to events room_tpl.html <div {{ SendMsg room = this.room }} > <div> <input type="text" name="text" placeholder="Enter message" {{ SendMsg_msgText }} {{ sunny_trigger }} /> </div> <button {{ sunny_trigger }} >Send</button> </div> html5 data attributes specify event type and parameters dynamically discovered and triggered asynchronously no need for any Ajax requests/responses – the data-binding mechanism will automatically kick in 32

  70. Adding New Features: adding a field implement user status messages 33

  71. Adding New Features: adding a field implement user status messages all it takes: user class User <p {{ editableField obj = this.user fld = "status" }} > status: Text {{ this.user.status }} </p> 33

  72. Adding New Features: adding a field implement user status messages all it takes: user class User <p {{ editableField obj = this.user fld = "status" }} > status: Text {{ this.user.status }} </p> demo 33

  73. Security/Privacy: write policies forbid changing other people’s data by default, all fields are public policies used to specify access restrictions 34

  74. Security/Privacy: write policies forbid changing other people’s data by default, all fields are public policies used to specify access restrictions policy User, update: "*" : (usr, val) -> return this . allow () if usr. equals ( this .client ? .user) return this . deny ("can’t edit other people’s data") 34

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend