This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-02-12
Channels
- # babashka (22)
- # beginners (112)
- # calva (7)
- # cider (2)
- # clj-kondo (43)
- # cljdoc (25)
- # cljsrn (30)
- # clojars (16)
- # clojure (73)
- # clojure-australia (2)
- # clojure-bay-area (8)
- # clojure-europe (16)
- # clojure-finland (1)
- # clojure-italy (2)
- # clojure-nl (7)
- # clojure-uk (9)
- # clojurescript (28)
- # clojureverse-ops (2)
- # conjure (2)
- # css (22)
- # cursive (28)
- # datomic (9)
- # depstar (28)
- # emacs (6)
- # fulcro (39)
- # graalvm (61)
- # honeysql (38)
- # instaparse (3)
- # jobs (1)
- # kaocha (3)
- # malli (7)
- # pathom (83)
- # sql (3)
- # tools-deps (18)
- # vim (2)
- # xtdb (15)
Is there a widely-used, well-documented library for implementing role-based access control in Clojure? I imagine it's often pretty domain-specific and mostly just simple checks on maps/sets etc., but wanted to see if there was something nice out there.
@UH85MNSKE I'm one the look out for one too - sorry if not helpful, but let's compare notes if either of us finds something 😉
tbh I wasn't gonna look that hard, seems pretty easy to roll your own. But I saved your message to come back to just in case. 🙂
Did ya'll find anything suitable here? I've found • permissions https://github.com/tuhlmann/permissions • and zakon https://github.com/fmnoise/zakon
Permissions looks really cool, interestingly a part of our system already does something like that so (assuming it works as expected) migration would be almost seamless. Thanks for sharing @U70QFSCG2!
permissions is cljc, so would work in cljs, unlike zakon. though I don't see why zakon couldn't work in cljs.
permissions can be initialized with just data, whereas zakon has a macro. though with that macro, zakon lets you supply arbitrary functions as authorizers. both rely on global state which is less than ideal if you have dynamic roles/permissions stored in a db
Look here https://github.com/tuhlmann/permissions/blob/master/test/agynamix/roles_test.cljc#L6-L31
then notice how none of the has-permission?
calls pass the available roles, as they are read from the atom
Should be easy to fix though and refactor the code to allow for passing a role map rather than sourcing it from a global atom
hm, or you can supply custom resolvers here: https://github.com/tuhlmann/permissions/blob/master/src/agynamix/roles.cljc#L100-L104
I'm trying to attach some metadata to a def
ed fn
inside of a macro, but nothing quite seems to stick:
(let [doc "docs"
meta {:arglists '([test])}]
`(def ^~meta foo ~doc (fn [x] 1)))
;; => error: Metadata must be Symbol,Keyword,String or Map
But when I check, it says it's a map:
(let [meta {:arglists '([test])}]
`[~(type meta)])
;;=> [clojure.lang.PersistentArrayMap]
try:
~(with-meta 'foo meta)
I think it's trying to apply the metadata '~ to the symbol meta
in your example
actually. it's probably trying to add the metadata ~meta
to the symbol foo
> (defmacro test-fn-meta []
`(def ~(with-meta 'foo {:a 1}) (fn [])))
> (test-fn-meta)
#'my.ns/foo
> (meta #'foo)
{:a 1,
:line 929,
:column 18,
:file "*cider-repl examples/browser:localhost:49996(clj)*",
:name foo,
}
ah, that makes perfect sense. I'm adding the meta to the var, I had tried wrapping the fn
before but that obviously doesn't do what I'm aiming for
as an improvement, defn
allows an optional map between the name and params that will be added to the metadata:
(defmacro test-fn-meta []
`(defn ~'foo ~{:a 1} [x] 1))
I had tried that, but in my (brief) test I couldn't override the :arglists, it just used the ones from the actual arg vector
ok, I got everything working the way I wanted in clj, but when I tried using it in cljs I found a weird behavior with arglists:
(defn bar {:b 2 :arglists '([damned lies])}
[x] 1)
(meta #'bar)
;;=> {:ns user, :name bar, :file "user/main.cljs", :end-column 10, :source "bar", :column 1, :line 1, :b 2, :end-line 1, :arglists ([damned lies]), :doc nil, :test nil}
;; this is just like clj^
(defn foo {:a 1 :arglists '([lies])}
([x] 1)
([x y] 2))
(meta #'foo)
;;=> {:ns user, :name foo, :file "user/main.cljs", :end-column 10, :top-fn {:variadic? false, :fixed-arity 2, :max-fixed-arity 2, :method-params [[x] [x y]], :arglists ([x] [x y]), :arglists-meta (nil nil)}, :source "foo", :column 1, :line 1, :end-line 1, :arglists ([x] [x y]), :doc "docs", :test nil, :a 1}
according the docs, cljs has no reified vars, https://www.clojurescript.org/about/differences#_vars_and_the_global_environment the truth is a little bit trickier as there's been a few improvements that address some of the use cases of reified vars. overall, I've found it's worth avoiding vars in cljs if possible. That may change as they keep improving cljs
It looks like multi-arity functions will override the :arglists supplied in the metadata with the ones it figures out on its own
(apply distinct? [1 2 3 4 2])
=> false
(apply distinct? [1 2 3 4])
=> true
would prefer this over frequencies since it will short circuit on first repeat
That's the one, thanks!
I used borkdude's re-find
but I didn't guess to try vararg as opposed to a single collection.
How can I split a string by (char 1)
;;; works, is there a better way?
(vec (.split (str "asdf" (char 1) "asdf") (str (char 1))))
;;; these don't work
(str/split (str "asdf" (char 1) "asdf")
#"\u00001"
;;#"[\\1]"
;;#"\\x01"
)
I get the same result for these two subexpressions. You do not?
user=> (= (vec (.split s1 (str (char 1)))) (str/split s1 #"\u0001"))
true
And in fact, for your first and third options that you say didn't work for you:
user=> (require '[clojure.string :as str])
nil
user=> (def s1 (str "asdf" (char 1) "asdf"))
user=> (def a1 (vec (.split s1 (str (char 1)))))
#'user/a1
user=> (def a2 (str/split s1 #"\u0001"))
#'user/a2
user=> (def a3 (str/split s1 #"\x01"))
#'user/a3
user=> (= a1 a2 a3)
true
(Note that inside a Clojure string surrounded by "", you need to type \\
to get a single backslash. Inside of #"" you only need to type one backslash to get one backslash in the regex string -- the Clojure reader parses regex strings slightly differently than regular strings, as a convenience to avoid having to type so many double backslashes)
but that can lead to more confusion if you weren't aware of it (and I just double-checked -- this fact is documented in official docs here if you search for regex: https://clojure.org/reference/reader)
if you have a function that will end up reifying a java.util.Comparator
, do you ask the caller to supply a function satisfying the <0,0,>0 contract that a comparator expects and reify it inside the function or do you have the caller just pass you a java.util.Comparator and not worry about it since its clear at the call site that you have that contract?
i guess, do you make everyone go through the ceremony of reify'ing or take a function and do the reify in one spot for conveinece to the caller
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/AFunction.java#L50
What Java version do folks recommend or are using for prod? We're looking to upgrade from Java 8 but aren't sure how high is safe to go. Obviously we'll test things out well before we ship, just looking for a recommendation on a target.
My feeling on Java versions is the same for Clojure projects as it is for Java projects: if you want to play with the non-LTS releases, that’s great; if it’s for production code, stick with the LTS Javas: 11, 17, 23… Not everyone feels the same way, of course. If you’re in the Java space, you might want to play with some of the features but in Clojure dev, I think it’s even less compelling as it’s not like there are significant VM changes occurring.
I agree. Even though we are using Adopt OpenJDK versions, rather than Oracle's versions, we feel more comfortable with 11 in production and plan to move to 17 at some point. In dev we've been testing against 11, 14, and I'm currently using 15 -- but I can easily run tests against multiple versions just by using an env var (I have four or five different JDKs installed locally).
I don't recall hitting any problems when I moved up to JDK 14, except for some minor changes in locale-specific number formatting (which I think were bug fixes -- but they broke a couple of our tests).
But locale-specific number formatting has changed a little across several recent JDK versions so that wasn't entirely surprising.
The big jump was from 8 to 11 (because of all the changes in 9). Since then it's been pretty smooth sailing.
Java 10 or 11 introduced some important changes if you are running in a container (making JVM pay attention to container settings)
so if you're doing that, it's almost definitely worth upgrading from 8 to 11
as of this year, the clojure community has shifted from majority 8 to 11
We still have to maintain JDK 8 compatibility in most of our code because we have a legacy app that we're still slowly rewriting to Clojure and it won't run on JDK 9+ (it's a mix of Clojure and... other stuff... 🙂 ).
officially, we test and recommend Clojure only on LTS Java releases. unofficially, I test it with each release and am not aware of any issues on recent versions
its only if you are on a platform that dictates your java version or you plan on paying for paid support that what companies consider LTS in java starts to matter