Skip to content

Commit 4088194

Browse files
committed
Merge branch 'edge' of github.com:hyperstack-org/hyperstack into edge
2 parents a222222 + 823b794 commit 4088194

File tree

7 files changed

+918
-692
lines changed

7 files changed

+918
-692
lines changed

docs/dsl-client/hyper-component.md

Lines changed: 199 additions & 72 deletions
Large diffs are not rendered by default.

docs/dsl-client/hyper-store.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Stores
22

33
**Work in progress - ALPHA (docs and code)**
4+
**These docs are out of date**
45

56
Hyperstack **Stores** are implemented in the **HyperStore Gem**.
67

docs/dsl-isomorphic/hyper-policy.md

Lines changed: 107 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -2,113 +2,6 @@
22

33
**WORK IN PROGRESS DOCS**
44

5-
First as you say to explicitly send stuff to all applicants. Policies work "backwards" to how you might think in a controller. In a controller you might check something like acting_user.chatrooms.include?(message.chatroom) whereas Hyperloop starts from the other end, it'll effectively do something like this message.chatroom.participants.include?(acting_user). Your job in a policy is to start with the actual record, then traverse the relationships to return the user or users it belongs to. Think in terms of "I have a thing, who are all the people who are allowed to see it?".
6-
Now that may or may not work in your case. If you have anonymous accounts for applicants but they all still have user records and thus IDs then it will work — job_posting.hiring_manager.applicants. But if applicants didn't have any record then you couldn't use this style of "instance channel policy". Instance == ids == non-public. So if something is public you can use a class channel. send_all.to(Applicant).
7-
Finally you can have many channels or just a few. In our app I've gone with a user instance channel, and a user class channel. That's just what works for my mental model. But you could have other instance and class channels to make dividing things up easier, your scope chains shorter, etc.
8-
Hopefully you can look at the docs now and see instance, class, channel, broadcast, etc. and come up with a way that works for you. Mitch's snippet looks good, I just tried to give some surrounding color.
9-
10-
The policy send all bit is about once you've got a record/records, are you allowed to see it and what attributes are you allowed to see (in that case all, but you can permit a subset).
11-
The regulate bit is about what relations are you allowed to access. It may seem redundant as without regulations event if you loaded the relation you still wouldn't be able see any of the record attributes without a policy. So even without regulations there's no risk of exposing private information. BUT what would leak is lists IDs and counts. A count doesn't instantiate any records so there's nothing to run a policy on. Leaking counts and IDs is metadata that may or may not be sensitive, aka you wouldn't want an insurance company to be able to do patient.diseases.count. And if you're using UUIDs so you don't sequentially leak all of your public pages, again you'd want a regulation to protect that. They can also prevent denial of service attacks loading big expensive relations.
12-
So, broadcast policies are about who can see the attributes of an individual record (or collection but it's still run on each record individually). Regulations are about preventing business data leakage.
13-
14-
------------
15-
16-
from Mitch...
17-
18-
These work very similar to pundit, and by design you can even mix pundit and hyperloop policies.
19-
Here is an example pundit policy from the pundit tutorial:
20-
21-
# app/policies/article_policy.rb
22-
class ArticlePolicy < ApplicationPolicy
23-
def index?
24-
true
25-
end
26-
27-
def create?
28-
user.present?
29-
end
30-
31-
def update?
32-
return true if user.present? && user == article.user
33-
end
34-
35-
def destroy?
36-
return true if user.present? && user == article.user
37-
end
38-
39-
private
40-
41-
def article
42-
record
43-
end
44-
end
45-
46-
--------------
47-
48-
class ArticlePolicy < ApplicationPolicy
49-
# def index?
50-
# true
51-
# end
52-
53-
# read policies are defined as part of broadcast policies. (if you can receive
54-
# it in a broadcast then you can read it)
55-
# There is no controller in hyperloop so broadcast/read policies
56-
# are defined in terms of what data is sent to what channel
57-
58-
regulate_broadcast do |policy|
59-
policy.send_all.to Application
60-
end
61-
62-
# def create?
63-
# user.present? <- create is okay if user is not nil
64-
# end
65-
66-
allow_create { acting_user } # <- create is okay if acting_user is not nil
67-
68-
# def update?
69-
# return true if user.present? && user == article.user
70-
# end
71-
72-
# only difference is hyperloop makes it easier by
73-
# 1) running the block with self == the the record
74-
# 2) adding the acting_user method to self
75-
# 3) treating exceptions as the same as nil
76-
77-
allow_update { acting_user == user }
78-
79-
# def destroy?
80-
# return true if user.present? && user == article.user
81-
# end
82-
83-
allow_destroy { acting_user == user }
84-
85-
# the above two regulations are the same and so can be dried up like this:
86-
87-
allow_change(on: [:update, :destroy]) { acting_user == user }
88-
89-
# private
90-
#
91-
# def article
92-
# record
93-
# end
94-
end
95-
96-
without comments....
97-
98-
class ArticlePolicy < ApplicationPolicy
99-
regulate_broadcast { |policy| policy.send_all.to Application }
100-
101-
allow_create { acting_user } # <- create is okay if acting_user is not nil
102-
103-
allow_change(on: [:update, :destroy]) { acting_user == user }
104-
end
105-
106-
BTW what if you want to restrict what data is broadcast? In Hyperloop you just update the regulation. In pundit you may have to edit both the index controller method and
107-
Policy class.
108-
109-
110-
**Work in progress - ALPHA (docs and code)**
111-
1125
## Authorization
1136

1147
Access to your Isomorphic Models is controlled by *Policies* that describe how the current *acting_user* and *channels* may access your Models.
@@ -596,3 +489,110 @@ class ProductionCenterPolicy < MyPolicyClass
596489
...
597490
end
598491
```
492+
493+
---------------------------
494+
TODO: rewrite the following:
495+
496+
First as you say to explicitly send stuff to all applicants. Policies work "backwards" to how you might think in a controller. In a controller you might check something like acting_user.chatrooms.include?(message.chatroom) whereas Hyperloop starts from the other end, it'll effectively do something like this message.chatroom.participants.include?(acting_user). Your job in a policy is to start with the actual record, then traverse the relationships to return the user or users it belongs to. Think in terms of "I have a thing, who are all the people who are allowed to see it?".
497+
Now that may or may not work in your case. If you have anonymous accounts for applicants but they all still have user records and thus IDs then it will work — job_posting.hiring_manager.applicants. But if applicants didn't have any record then you couldn't use this style of "instance channel policy". Instance == ids == non-public. So if something is public you can use a class channel. send_all.to(Applicant).
498+
Finally you can have many channels or just a few. In our app I've gone with a user instance channel, and a user class channel. That's just what works for my mental model. But you could have other instance and class channels to make dividing things up easier, your scope chains shorter, etc.
499+
Hopefully you can look at the docs now and see instance, class, channel, broadcast, etc. and come up with a way that works for you. Mitch's snippet looks good, I just tried to give some surrounding color.
500+
501+
The policy send all bit is about once you've got a record/records, are you allowed to see it and what attributes are you allowed to see (in that case all, but you can permit a subset).
502+
The regulate bit is about what relations are you allowed to access. It may seem redundant as without regulations event if you loaded the relation you still wouldn't be able see any of the record attributes without a policy. So even without regulations there's no risk of exposing private information. BUT what would leak is lists IDs and counts. A count doesn't instantiate any records so there's nothing to run a policy on. Leaking counts and IDs is metadata that may or may not be sensitive, aka you wouldn't want an insurance company to be able to do patient.diseases.count. And if you're using UUIDs so you don't sequentially leak all of your public pages, again you'd want a regulation to protect that. They can also prevent denial of service attacks loading big expensive relations.
503+
So, broadcast policies are about who can see the attributes of an individual record (or collection but it's still run on each record individually). Regulations are about preventing business data leakage.
504+
505+
------------
506+
507+
from Mitch...
508+
509+
These work very similar to pundit, and by design you can even mix pundit and hyperloop policies.
510+
Here is an example pundit policy from the pundit tutorial:
511+
512+
# app/policies/article_policy.rb
513+
class ArticlePolicy < ApplicationPolicy
514+
def index?
515+
true
516+
end
517+
518+
def create?
519+
user.present?
520+
end
521+
522+
def update?
523+
return true if user.present? && user == article.user
524+
end
525+
526+
def destroy?
527+
return true if user.present? && user == article.user
528+
end
529+
530+
private
531+
532+
def article
533+
record
534+
end
535+
end
536+
537+
--------------
538+
539+
class ArticlePolicy < ApplicationPolicy
540+
# def index?
541+
# true
542+
# end
543+
544+
# read policies are defined as part of broadcast policies. (if you can receive
545+
# it in a broadcast then you can read it)
546+
# There is no controller in hyperloop so broadcast/read policies
547+
# are defined in terms of what data is sent to what channel
548+
549+
regulate_broadcast do |policy|
550+
policy.send_all.to Application
551+
end
552+
553+
# def create?
554+
# user.present? <- create is okay if user is not nil
555+
# end
556+
557+
allow_create { acting_user } # <- create is okay if acting_user is not nil
558+
559+
# def update?
560+
# return true if user.present? && user == article.user
561+
# end
562+
563+
# only difference is hyperloop makes it easier by
564+
# 1) running the block with self == the the record
565+
# 2) adding the acting_user method to self
566+
# 3) treating exceptions as the same as nil
567+
568+
allow_update { acting_user == user }
569+
570+
# def destroy?
571+
# return true if user.present? && user == article.user
572+
# end
573+
574+
allow_destroy { acting_user == user }
575+
576+
# the above two regulations are the same and so can be dried up like this:
577+
578+
allow_change(on: [:update, :destroy]) { acting_user == user }
579+
580+
# private
581+
#
582+
# def article
583+
# record
584+
# end
585+
end
586+
587+
without comments....
588+
589+
class ArticlePolicy < ApplicationPolicy
590+
regulate_broadcast { |policy| policy.send_all.to Application }
591+
592+
allow_create { acting_user } # <- create is okay if acting_user is not nil
593+
594+
allow_change(on: [:update, :destroy]) { acting_user == user }
595+
end
596+
597+
BTW what if you want to restrict what data is broadcast? In Hyperloop you just update the regulation. In pundit you may have to edit both the index controller method and
598+
Policy class.

docs/readme.md

Lines changed: 65 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,72 @@
11
# Welcome to Hyperstack!
22

3-
We are in the process of renaming Hyperloop to Hyperstack, so these docs will reference Hyperstack while the code uses Hyperloop.
3+
## Hyperstack
44

5-
Alfie is about to finish his bone.
5+
Hyperstack is a Ruby-based DSL and modern web toolkit for building spectacular, interactive web applications fast!
66

7-
## Hyperstack
7+
+ **One language** throughout the client and server. All Ruby code is compiled by [Opal](https://opalrb.com/) into JavaScript automatically.
8+
+ Webpacker and Yarn tooling for a **modern, fast hot-reloader build environment with Ruby source maps**.
9+
+ A well documented and stable Ruby DSL for wrapping **React** and **ReactRouter** as well as **any** JavaScript library or component. No need to learn JavaScript!
10+
+ **Isomorphic Models with bi-directional data** so you can access your models as if they were on the client.
11+
12+
All that means you can write simple front-end code like this:
13+
14+
```ruby
15+
class GoodBooksToRead < Hyperstack::Component
16+
render(UL) do
17+
Book.good_books.each do |book|
18+
LI { "Read #{book.name}" }.on(:click) { display book } if book.available?
19+
end
20+
end
21+
end
22+
```
23+
24+
In the code above, if the `good_books` scope changed (even on the server), the UI would update automatically. That's the magic of React and Isomorphic Models with bi-directional data at work!
25+
26+
## Website and documentation
27+
28+
+ Website: [hyperstack.org](https://hyperstack.org)
29+
30+
Our website serves as a Hyperstack example application. All the doc content is loaded dynamically from this repo and converted to HTML on the fly. It uses React Semantic UI and a client-side JavaScript full-text search engine. Its a Rails app hosted on Heroku.
31+
32+
## Setup and installation
33+
34+
You can be up and running in **less than 5 minutes**. Just follow the simple setup guide for a new Rails application all correctly configured and ready to go with Hyperstack.
35+
36+
+ Setup and Installation: [https://hyperstack.org/edge/docs/installation)
37+
38+
## Community and support
39+
40+
Hyperstack is supported by a friendly, helpful community, both for users, and contributors. We welcome new people, please reach out and say hello.
41+
42+
+ Reach us at: [Gitter chat](https://gitter.im/ruby-hyperloop/chat)
43+
44+
## Roadmap
45+
46+
Hyperstack is evolving; we are improving it all the time. As much as we love Ruby today, we see ourselves embracing new languages in the future. [Crystal](https://crystal-lang.org/) perhaps? We are also watching [Wasm](https://webassembly.org/) carefully.
47+
48+
Please see the [ROADMAP](https://github.com/hyperstack-org/hyperstack/blob/edge/ROADMAP.md) for more information.
49+
50+
## Contributing
51+
52+
If you would like to help, please read the [CONTRIBUTING](https://github.com/hyperstack-org/hyperstack/blob/edge/CONTRIBUTING.md) file for suggestions.
53+
54+
## Links
55+
56+
+ Rubygems: https://rubygems.org/profiles/hyperstack
57+
+ Travis: https://travis-ci.org/hyperstack-org
58+
+ Website edge: https://edge.hyperstack.org/
59+
+ Website master: https://hyperstack.org/
60+
61+
## License
62+
63+
Released under the MIT License. See the [LICENSE][https://github.com/hyperstack-org/hyperstack/blob/edge/LICENSE] file for further details.
864

9-
+ Webiste: https://hyperstack.org/
10-
+ Github: https://github.com/hyperstack-org
65+
## History
1166

12-
## RubyHyperloop legacy
67+
Hyperstack is an evolution of [Ruby-Hyperloop](https://github.com/ruby-hyperloop). We decided to rename the project to drop the Ruby suffix and also took the opportunity to simplify the repos and project overall.
1368

14-
+ RubyHyperloop (legacy version 0.99.x) is production ready and very stable
15-
+ This hyperloop-legacy branch will only contain critical bug fixes
16-
+ The original website is here: http://ruby-hyperloop.org/
17-
+ The final stable branch is https://github.com/hyperstack-org/hyperstack/tree/hyperloop-legacy
18-
69+
+ Old website: http://ruby-hyperloop.org/
70+
+ Old Github: https://github.com/ruby-hyperloop
71+
+ Legacy branch: https://github.com/hyperstack-org/hyperstack/tree/hyperloop-legacy
72+
+ Legacy install script: https://github.com/hyperstack-org/hyperstack/tree/hyperloop-legacy/install

0 commit comments

Comments
 (0)