├── tests.edn
├── .gitignore
├── CHANGELOG.md
├── project.clj
├── test
└── can
│ ├── bitmask_test.cljc
│ └── can_test.cljc
├── src
└── can
│ ├── can.cljc
│ └── bitmask.cljc
├── README.md
└── LICENSE
/tests.edn:
--------------------------------------------------------------------------------
1 | #kaocha/v1
2 | {:tests [{:id :unit-cljs
3 | :type :kaocha.type/cljs}]}
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 | *.jar
3 | *.swp
4 | .classpath
5 | .cljs_node_repl/
6 | .hg/
7 | .hgignore
8 | .project
9 | .settings/
10 | /.lein-*
11 | /.nrepl-port
12 | /checkouts
13 | /classes
14 | /node_modules
15 | /target
16 | out/
17 | package-lock.json
18 | pom.xml
19 | pom.xml.asc
20 | profiles.clj
21 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## Unreleased
4 | ### New features
5 |
6 | * `can.can/allow?` supports domain-only checks; this simplifies code that
7 | checks whether a domain is (generally) permissible, e.g., to determine
8 | whether to display the admin UI (of admin domain). While this could be
9 | done with `(contains? permissions domain-key)`, the intent is clearer
10 | with `can.can/allow? permissions domain-key)`.
11 |
--------------------------------------------------------------------------------
/project.clj:
--------------------------------------------------------------------------------
1 | (defproject can "0.4.0-SNAPSHOT"
2 | :description "Permissions library for Clojure[Script]"
3 | :url "https://github.com/shaolang/can"
4 | :license {:name "EPL-2.0"
5 | :url "https://www.eclipse.org/legal/epl-2.0/"}
6 |
7 | :aliases {"test-cljs" ["trampoline" "run" "-m" "kaocha.runner" "unit-cljs"]}
8 |
9 | :profiles {:dev {:dependencies [[lambdaisland/kaocha "1.0.829"]
10 | [lambdaisland/kaocha-cljs "0.0-71"]
11 | [org.clojure/clojure "1.10.3"]]}}
12 |
13 | :repl-options {:init-ns can.can}
14 |
15 | :scm {:name "git"
16 | :url "https://github.com/shaolang/can"})
17 |
--------------------------------------------------------------------------------
/test/can/bitmask_test.cljc:
--------------------------------------------------------------------------------
1 | (ns can.bitmask-test
2 | (:require #?(:clj [clojure.test :refer [deftest is testing]]
3 | :cljs [cljs.test :refer-macros [deftest is testing]])
4 | [can.bitmask :as bitmask]))
5 |
6 | (deftest decode-test
7 | (let [all-permissions {:admin [:create :read :update :delete]
8 | :support [:create-tix :read-tix :edit-tix :delete-tix]
9 | :printers [:print]}
10 | bitmasks {:admin 5 :support 4 :printers 0}]
11 | (is (= {:admin #{:create :update}
12 | :support #{:edit-tix}}
13 | (bitmask/decode all-permissions bitmasks)))
14 |
15 | (is (= {:admin #{:*}}
16 | (bitmask/decode all-permissions {:admin 15})))))
17 |
18 |
19 | (deftest encode-test
20 | (let [all-permissions {:admin [:create :read :update :delete]
21 | :support [:create-tix :read-tix :edit-tx :delete-tix]}
22 | user-permissions {:admin #{:create :delete}
23 | :support #{:*}
24 | :printer #{:print}}]
25 | (is (= {:admin 9 :support 15}
26 | (bitmask/encode all-permissions user-permissions)))
27 |
28 | (is (= {:admin 1 :support 0}
29 | (bitmask/encode all-permissions {:admin #{:create}})))))
30 |
--------------------------------------------------------------------------------
/src/can/can.cljc:
--------------------------------------------------------------------------------
1 | (ns can.can
2 | (:require [clojure.set :as set]
3 | [clojure.string :as str]))
4 |
5 | (defn- subset? [xs ys]
6 | (set/subset? (set xs) (set ys)))
7 |
8 |
9 | (defn actions->permissions
10 | ([actions]
11 | (->> actions
12 | (map #(map keyword (str/split % #":")))
13 | (group-by first)
14 | (map (fn [[k vs]] [k (set (map second vs))]))
15 | (into {})))
16 | ([domain-actions actions]
17 | (let [permissions (actions->permissions actions)
18 | domains (set (keys domain-actions))]
19 | (if (and (subset? (keys permissions) domains)
20 | (every? (fn [[k vs]] (subset? vs (get domain-actions k)))
21 | permissions))
22 | permissions
23 | :unknown-domain-action-found))))
24 |
25 |
26 | (defn allow? [permissions action]
27 | (let [[domain action] (->> (str/split action #":")
28 | (map keyword))
29 | actions (get permissions domain (:* permissions))]
30 | (boolean (when-not (or (= action :*) (= domain :*))
31 | (or (some #{action} actions)
32 | (some #{:*} actions)
33 | (and (contains? permissions domain)
34 | (nil? action)))))))
35 |
36 |
37 | (defn permissions->actions [full-permissions permissions]
38 | (->> permissions
39 | (map (fn [[k vs]]
40 | (let [kstr (name k)
41 | vs (if (some #{:*} vs) (get full-permissions k) vs)]
42 | [k (set (map #(str kstr %) vs))])))
43 | (into {})))
44 |
--------------------------------------------------------------------------------
/src/can/bitmask.cljc:
--------------------------------------------------------------------------------
1 | (ns can.bitmask
2 | (:require [clojure.string :as str]))
3 |
4 |
5 | (defn- actions->bitmask-map [actions]
6 | (zipmap (iterate #(* 2 %) 1) actions))
7 |
8 |
9 | (defn- on-all-bitmasks [actions]
10 | (dec (int (Math/pow 2 (count actions)))))
11 |
12 |
13 | (defn- bitmask->granted-actions [bitmask actions]
14 | (if (= bitmask (on-all-bitmasks actions))
15 | #{:*}
16 | (let [bitmask-actions (actions->bitmask-map actions)
17 | granted-actions (for [[action-bit action] bitmask-actions]
18 | (when (pos? (bit-and bitmask action-bit))
19 | action))
20 | granted-actions (filter (complement nil?) granted-actions)]
21 | (when-not (empty? granted-actions)
22 | (into #{} (filter (complement nil?) granted-actions))))))
23 |
24 | (defn- parse-long [s]
25 | #?(:clj (Long/parseLong s)
26 | :cljs (js/parseInt s)))
27 |
28 |
29 | (defn decode [all-permissions domain-bitmasks]
30 | (let [permissions (for [[domain bitmask] domain-bitmasks]
31 | (let [actions (get all-permissions domain)
32 | granted-actions (bitmask->granted-actions bitmask
33 | actions)]
34 | (when-not (nil? granted-actions)
35 | (hash-map domain granted-actions))))]
36 | (apply merge {} permissions)))
37 |
38 |
39 | (defn- granted-actions->bitmask [granted-actions all-domain-actions]
40 | (if (= granted-actions #{:*})
41 | (on-all-bitmasks all-domain-actions)
42 | (let [bitmask-actions (actions->bitmask-map all-domain-actions)]
43 | (transduce (comp (filter (fn [[_ action]] (some #{action} granted-actions)))
44 | (map first))
45 | +
46 | bitmask-actions))))
47 |
48 |
49 | (defn encode [all-permissions granted-permissions]
50 | (->> all-permissions
51 | (map (fn [[domain all-actions]]
52 | [domain (granted-actions->bitmask (get granted-permissions domain)
53 | all-actions)]))
54 | (into {})))
55 |
--------------------------------------------------------------------------------
/test/can/can_test.cljc:
--------------------------------------------------------------------------------
1 | (ns can.can-test
2 | (:require #?(:clj [clojure.test :refer [are deftest is testing]]
3 | :cljs [cljs.test :refer-macros [are deftest is testing]])
4 | [can.can :as can]))
5 |
6 | (deftest allow?-test
7 | (let [permissions {:admin #{:create :read :update :delete}
8 | :support #{:create-ticket :close-ticket}
9 | :audit #{:*}}]
10 | (are [action expected] (and action
11 | (= (can/allow? permissions action) expected))
12 |
13 | ;; input expected
14 | "admin:create" true ;; specified domain and known action
15 | "audit:print-log" true ;; specified domain with wildcard action
16 | "admin:approve" false ;; specified domain but unknown action
17 | "misc:print" false ;; unknown domain and unknown action
18 | "*:create" false ;; wildcard domain
19 | "admin" true ;; domain only check
20 | "*" false ;; domain-only cannot be a wildcard
21 | "create" false)) ;; action only check
22 |
23 | (let [permissions {:* #{:*}}] ;; [almost] anything allowed
24 | (are [action expected] (= (can/allow? permissions action) expected)
25 |
26 | ;;input expected
27 | "hello:world" true ;; allows everything
28 | "*:delete" false ;; domain cannot be a wildcard
29 | "misc:*" false ;; user action cannot be a wildcard
30 | "admin" true ;; domain only check
31 | "*" false))) ;; domain-only cannot be a wildcard
32 |
33 |
34 | (deftest actions->permissions-test
35 | (testing "with no full domain/action map given"
36 | (is (= {:admin #{:create :read}
37 | :support #{:close-ticket}}
38 | (can/actions->permissions
39 | ["admin:create" "admin:read" "support:close-ticket"]))))
40 |
41 | (testing "identical domain/action names are handled properly"
42 | (is (= {:support #{:support}}
43 | (can/actions->permissions ["support:support"]))))
44 |
45 | (testing "with full domain-action map given with no unknown action given"
46 | (is (= {:admin #{:delete}
47 | :support #{:edit-ticket}}
48 | (can/actions->permissions {:admin #{:create :read :update :delete}
49 | :support #{:create-ticket :edit-ticket}}
50 | ["admin:delete" "support:edit-ticket"]))))
51 |
52 | (testing "with full domain-action map given and unknown action given"
53 | (is (= :unknown-domain-action-found
54 | (can/actions->permissions {:admin #{:create :read}
55 | :support #{:create-ticket}}
56 | ["admin:create" "support:edit-ticket"])))))
57 |
58 |
59 | (deftest permissions->actions-test
60 | (is (= {:admin #{"admin:create" "admin:read" "admin:update" "admin:delete"}
61 | :support #{"support:create-ticket"}}
62 | (can/permissions->actions {:admin #{:create :read :update :delete}
63 | :support #{:create-ticket :edit-ticket}}
64 | {:admin #{:*}
65 | :support #{:create-ticket}}))))
66 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # can
2 | [](https://clojars.org/can)
3 |
4 | A permissions library for Clojure(Script), inspired by
5 | [agynamix/permissions][permissions].
6 |
7 | __Library is still undergoing development, so expect frequent changes
8 | to the API.__
9 |
10 | ## Basic Usage
11 |
12 | The core API lives in `can.can` (not `can.core`) and is recommended
13 | to be aliased as `can`, i.e., `(require '[can.can :as can])`.
14 |
15 | Permissions is a map of sets, where the key is the domain, and the
16 | values the rights applicable to that domain. `can.can/allow?` takes
17 | the permissions map and an domain/action string to determine whether
18 | the user is allowed to perform the said action:
19 |
20 | ```clojure
21 | (def permissions {:support #{:create-ticket :update-ticket}
22 | :printer #{:print}})
23 |
24 |
25 | (print (can/allow? permissions "support:create-ticket")) ;; outputs "true"
26 | (print (can/allow? permissions "print:clear-spool")) ;; outputs "false"
27 | ```
28 |
29 | You could also use `:*` to grant permissions:
30 |
31 | ```clojure
32 | (def super-support {:support #{:*}})
33 |
34 | (print (can/allow? super-support "support:launch-nuclear")) ;; outputs "true"
35 | (print (can/allow? super-support "print:clear-spool")) ;; outputs "false"
36 | ```
37 |
38 | And even superuser:
39 |
40 | ```clojure
41 | (def superuser {:* #{:*}})
42 |
43 | (print (can/allow? superuser "hello:world")) ;; outputs "true"
44 | ```
45 |
46 | Unlike permissions, actions cannot use `*`, i.e., doing
47 | `(can/allow? permissions "*:create-ticket")` or
48 | `(can/allow? permissions "admin:*")` will always return `false`.
49 |
50 | ## Bitmasks permissions
51 | __Breaking change in 0.3.0: bitmask-related functions reside in `can.bitmask`
52 | now, and they are renamed as decode and encode.__
53 |
54 | `can.bitmask/decode` takes the full permissions setup (i.e.,
55 | all available domains and actions available in your application) and
56 | converts a map of domain-bitmask pair into a permissions map.
57 |
58 | ```clojure
59 | (def all-permissions {:admin [:create :read :update :delete :approve :reject]
60 | :support [:create-ticket :update-ticket :close-ticket]
61 | :printer [:print :clear-spool]})
62 |
63 |
64 | (def alice-permissions
65 | (can/decode all-permissions {:admin 7 :printer 1}))
66 |
67 | (print alice-permissions) ;; outputs {:admin #{:create :read :update}
68 | ;; :printer #{:print}}
69 | ```
70 |
71 | Note that the order of the available actions in each domain matters, i.e.,
72 | new actions should be appended to the end of the action list.
73 |
74 | `can.bitmask/decode` makes it trivial to implement
75 | access control list/matrix in your application, e.g., the relational
76 | database could have a table that looks like the following:
77 |
78 |
79 |
80 |
81 | | userid |
82 | admin |
83 | support |
84 | printer |
85 |
86 |
87 |
88 | | alice | 7 | 0 | 1 |
89 | | bob | 0 | 7 | 2 |
90 |
91 |
92 |
93 | Note that when using bitmasks permissions, the total number of actions
94 | per domain cannot exceed 63 on Clojure, and cannot exceed 52 on
95 | ClojureScript.
96 |
97 | `can.bitmask/encode` converts the permissions map into a map of
98 | domain-bitmask pair (somewhat the inverse of `can.bitmask/decode`),
99 | making it easy to persist changes back to the datastore:
100 |
101 | ```clojure
102 | (print (encode all-permissions alice-permissions)) ;; outputs {:admin 7
103 | ;; :support 0
104 | ;; :printer 1}
105 | ```
106 |
107 | ## License
108 |
109 | Copyright © 2019 Shaolang Ai
110 |
111 | This program and the accompanying materials are made available under the
112 | terms of the Eclipse Public License 2.0 which is available at
113 | http://www.eclipse.org/legal/epl-2.0.
114 |
115 | [permissions]: https://github.com/tuhlmann/permissions
116 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Eclipse Public License - v 2.0
2 |
3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
4 | PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION
5 | OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
6 |
7 | 1. DEFINITIONS
8 |
9 | "Contribution" means:
10 |
11 | a) in the case of the initial Contributor, the initial content
12 | Distributed under this Agreement, and
13 |
14 | b) in the case of each subsequent Contributor:
15 | i) changes to the Program, and
16 | ii) additions to the Program;
17 | where such changes and/or additions to the Program originate from
18 | and are Distributed by that particular Contributor. A Contribution
19 | "originates" from a Contributor if it was added to the Program by
20 | such Contributor itself or anyone acting on such Contributor's behalf.
21 | Contributions do not include changes or additions to the Program that
22 | are not Modified Works.
23 |
24 | "Contributor" means any person or entity that Distributes the Program.
25 |
26 | "Licensed Patents" mean patent claims licensable by a Contributor which
27 | are necessarily infringed by the use or sale of its Contribution alone
28 | or when combined with the Program.
29 |
30 | "Program" means the Contributions Distributed in accordance with this
31 | Agreement.
32 |
33 | "Recipient" means anyone who receives the Program under this Agreement
34 | or any Secondary License (as applicable), including Contributors.
35 |
36 | "Derivative Works" shall mean any work, whether in Source Code or other
37 | form, that is based on (or derived from) the Program and for which the
38 | editorial revisions, annotations, elaborations, or other modifications
39 | represent, as a whole, an original work of authorship.
40 |
41 | "Modified Works" shall mean any work in Source Code or other form that
42 | results from an addition to, deletion from, or modification of the
43 | contents of the Program, including, for purposes of clarity any new file
44 | in Source Code form that contains any contents of the Program. Modified
45 | Works shall not include works that contain only declarations,
46 | interfaces, types, classes, structures, or files of the Program solely
47 | in each case in order to link to, bind by name, or subclass the Program
48 | or Modified Works thereof.
49 |
50 | "Distribute" means the acts of a) distributing or b) making available
51 | in any manner that enables the transfer of a copy.
52 |
53 | "Source Code" means the form of a Program preferred for making
54 | modifications, including but not limited to software source code,
55 | documentation source, and configuration files.
56 |
57 | "Secondary License" means either the GNU General Public License,
58 | Version 2.0, or any later versions of that license, including any
59 | exceptions or additional permissions as identified by the initial
60 | Contributor.
61 |
62 | 2. GRANT OF RIGHTS
63 |
64 | a) Subject to the terms of this Agreement, each Contributor hereby
65 | grants Recipient a non-exclusive, worldwide, royalty-free copyright
66 | license to reproduce, prepare Derivative Works of, publicly display,
67 | publicly perform, Distribute and sublicense the Contribution of such
68 | Contributor, if any, and such Derivative Works.
69 |
70 | b) Subject to the terms of this Agreement, each Contributor hereby
71 | grants Recipient a non-exclusive, worldwide, royalty-free patent
72 | license under Licensed Patents to make, use, sell, offer to sell,
73 | import and otherwise transfer the Contribution of such Contributor,
74 | if any, in Source Code or other form. This patent license shall
75 | apply to the combination of the Contribution and the Program if, at
76 | the time the Contribution is added by the Contributor, such addition
77 | of the Contribution causes such combination to be covered by the
78 | Licensed Patents. The patent license shall not apply to any other
79 | combinations which include the Contribution. No hardware per se is
80 | licensed hereunder.
81 |
82 | c) Recipient understands that although each Contributor grants the
83 | licenses to its Contributions set forth herein, no assurances are
84 | provided by any Contributor that the Program does not infringe the
85 | patent or other intellectual property rights of any other entity.
86 | Each Contributor disclaims any liability to Recipient for claims
87 | brought by any other entity based on infringement of intellectual
88 | property rights or otherwise. As a condition to exercising the
89 | rights and licenses granted hereunder, each Recipient hereby
90 | assumes sole responsibility to secure any other intellectual
91 | property rights needed, if any. For example, if a third party
92 | patent license is required to allow Recipient to Distribute the
93 | Program, it is Recipient's responsibility to acquire that license
94 | before distributing the Program.
95 |
96 | d) Each Contributor represents that to its knowledge it has
97 | sufficient copyright rights in its Contribution, if any, to grant
98 | the copyright license set forth in this Agreement.
99 |
100 | e) Notwithstanding the terms of any Secondary License, no
101 | Contributor makes additional grants to any Recipient (other than
102 | those set forth in this Agreement) as a result of such Recipient's
103 | receipt of the Program under the terms of a Secondary License
104 | (if permitted under the terms of Section 3).
105 |
106 | 3. REQUIREMENTS
107 |
108 | 3.1 If a Contributor Distributes the Program in any form, then:
109 |
110 | a) the Program must also be made available as Source Code, in
111 | accordance with section 3.2, and the Contributor must accompany
112 | the Program with a statement that the Source Code for the Program
113 | is available under this Agreement, and informs Recipients how to
114 | obtain it in a reasonable manner on or through a medium customarily
115 | used for software exchange; and
116 |
117 | b) the Contributor may Distribute the Program under a license
118 | different than this Agreement, provided that such license:
119 | i) effectively disclaims on behalf of all other Contributors all
120 | warranties and conditions, express and implied, including
121 | warranties or conditions of title and non-infringement, and
122 | implied warranties or conditions of merchantability and fitness
123 | for a particular purpose;
124 |
125 | ii) effectively excludes on behalf of all other Contributors all
126 | liability for damages, including direct, indirect, special,
127 | incidental and consequential damages, such as lost profits;
128 |
129 | iii) does not attempt to limit or alter the recipients' rights
130 | in the Source Code under section 3.2; and
131 |
132 | iv) requires any subsequent distribution of the Program by any
133 | party to be under a license that satisfies the requirements
134 | of this section 3.
135 |
136 | 3.2 When the Program is Distributed as Source Code:
137 |
138 | a) it must be made available under this Agreement, or if the
139 | Program (i) is combined with other material in a separate file or
140 | files made available under a Secondary License, and (ii) the initial
141 | Contributor attached to the Source Code the notice described in
142 | Exhibit A of this Agreement, then the Program may be made available
143 | under the terms of such Secondary Licenses, and
144 |
145 | b) a copy of this Agreement must be included with each copy of
146 | the Program.
147 |
148 | 3.3 Contributors may not remove or alter any copyright, patent,
149 | trademark, attribution notices, disclaimers of warranty, or limitations
150 | of liability ("notices") contained within the Program from any copy of
151 | the Program which they Distribute, provided that Contributors may add
152 | their own appropriate notices.
153 |
154 | 4. COMMERCIAL DISTRIBUTION
155 |
156 | Commercial distributors of software may accept certain responsibilities
157 | with respect to end users, business partners and the like. While this
158 | license is intended to facilitate the commercial use of the Program,
159 | the Contributor who includes the Program in a commercial product
160 | offering should do so in a manner which does not create potential
161 | liability for other Contributors. Therefore, if a Contributor includes
162 | the Program in a commercial product offering, such Contributor
163 | ("Commercial Contributor") hereby agrees to defend and indemnify every
164 | other Contributor ("Indemnified Contributor") against any losses,
165 | damages and costs (collectively "Losses") arising from claims, lawsuits
166 | and other legal actions brought by a third party against the Indemnified
167 | Contributor to the extent caused by the acts or omissions of such
168 | Commercial Contributor in connection with its distribution of the Program
169 | in a commercial product offering. The obligations in this section do not
170 | apply to any claims or Losses relating to any actual or alleged
171 | intellectual property infringement. In order to qualify, an Indemnified
172 | Contributor must: a) promptly notify the Commercial Contributor in
173 | writing of such claim, and b) allow the Commercial Contributor to control,
174 | and cooperate with the Commercial Contributor in, the defense and any
175 | related settlement negotiations. The Indemnified Contributor may
176 | participate in any such claim at its own expense.
177 |
178 | For example, a Contributor might include the Program in a commercial
179 | product offering, Product X. That Contributor is then a Commercial
180 | Contributor. If that Commercial Contributor then makes performance
181 | claims, or offers warranties related to Product X, those performance
182 | claims and warranties are such Commercial Contributor's responsibility
183 | alone. Under this section, the Commercial Contributor would have to
184 | defend claims against the other Contributors related to those performance
185 | claims and warranties, and if a court requires any other Contributor to
186 | pay any damages as a result, the Commercial Contributor must pay
187 | those damages.
188 |
189 | 5. NO WARRANTY
190 |
191 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
192 | PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS"
193 | BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
194 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF
195 | TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
196 | PURPOSE. Each Recipient is solely responsible for determining the
197 | appropriateness of using and distributing the Program and assumes all
198 | risks associated with its exercise of rights under this Agreement,
199 | including but not limited to the risks and costs of program errors,
200 | compliance with applicable laws, damage to or loss of data, programs
201 | or equipment, and unavailability or interruption of operations.
202 |
203 | 6. DISCLAIMER OF LIABILITY
204 |
205 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
206 | PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS
207 | SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
208 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
209 | PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
210 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
211 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
212 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
213 | POSSIBILITY OF SUCH DAMAGES.
214 |
215 | 7. GENERAL
216 |
217 | If any provision of this Agreement is invalid or unenforceable under
218 | applicable law, it shall not affect the validity or enforceability of
219 | the remainder of the terms of this Agreement, and without further
220 | action by the parties hereto, such provision shall be reformed to the
221 | minimum extent necessary to make such provision valid and enforceable.
222 |
223 | If Recipient institutes patent litigation against any entity
224 | (including a cross-claim or counterclaim in a lawsuit) alleging that the
225 | Program itself (excluding combinations of the Program with other software
226 | or hardware) infringes such Recipient's patent(s), then such Recipient's
227 | rights granted under Section 2(b) shall terminate as of the date such
228 | litigation is filed.
229 |
230 | All Recipient's rights under this Agreement shall terminate if it
231 | fails to comply with any of the material terms or conditions of this
232 | Agreement and does not cure such failure in a reasonable period of
233 | time after becoming aware of such noncompliance. If all Recipient's
234 | rights under this Agreement terminate, Recipient agrees to cease use
235 | and distribution of the Program as soon as reasonably practicable.
236 | However, Recipient's obligations under this Agreement and any licenses
237 | granted by Recipient relating to the Program shall continue and survive.
238 |
239 | Everyone is permitted to copy and distribute copies of this Agreement,
240 | but in order to avoid inconsistency the Agreement is copyrighted and
241 | may only be modified in the following manner. The Agreement Steward
242 | reserves the right to publish new versions (including revisions) of
243 | this Agreement from time to time. No one other than the Agreement
244 | Steward has the right to modify this Agreement. The Eclipse Foundation
245 | is the initial Agreement Steward. The Eclipse Foundation may assign the
246 | responsibility to serve as the Agreement Steward to a suitable separate
247 | entity. Each new version of the Agreement will be given a distinguishing
248 | version number. The Program (including Contributions) may always be
249 | Distributed subject to the version of the Agreement under which it was
250 | received. In addition, after a new version of the Agreement is published,
251 | Contributor may elect to Distribute the Program (including its
252 | Contributions) under the new version.
253 |
254 | Except as expressly stated in Sections 2(a) and 2(b) above, Recipient
255 | receives no rights or licenses to the intellectual property of any
256 | Contributor under this Agreement, whether expressly, by implication,
257 | estoppel or otherwise. All rights in the Program not expressly granted
258 | under this Agreement are reserved. Nothing in this Agreement is intended
259 | to be enforceable by any entity that is not a Contributor or Recipient.
260 | No third-party beneficiary rights are created under this Agreement.
261 |
262 | Exhibit A - Form of Secondary Licenses Notice
263 |
264 | "This Source Code may also be made available under the following
265 | Secondary Licenses when the conditions for such availability set forth
266 | in the Eclipse Public License, v. 2.0 are satisfied: {name license(s),
267 | version(s), and exceptions or additional permissions here}."
268 |
269 | Simply including a copy of this Agreement, including this Exhibit A
270 | is not sufficient to license the Source Code under Secondary Licenses.
271 |
272 | If it is not possible or desirable to put the notice in a particular
273 | file, then You may include the notice in a location (such as a LICENSE
274 | file in a relevant directory) where a recipient would be likely to
275 | look for such a notice.
276 |
277 | You may add additional accurate notices of copyright ownership.
278 |
--------------------------------------------------------------------------------