Fork me on GitHub
#beginners
<
2019-08-18
>
Matt00:08:27

I’m trying to figure out which frameworks are most popular for SPAs and Native applications. I know people like reagent and reframe, but I like om.next more. After hacking together JS libraries (eg. falcor + mobx + react) it’s a breath of fresh air. I know that fulcro exists, but I find it too heavy weight. Where are the best resources for digging into the om.next library, I find the GitHub wiki very lacking. It also makes me feel worried about the level of support for the library.

noisesmith18:08:08

om next seems cool, but last I checked it doesn't have the momentum and dev energy that reagent does

noisesmith18:08:54

so use it if it's useful, but maybe don't expect the amount of maintenance and feature work you'd see with a more popular lib? - looks like the last commit on the repo was over a year ago, which is ancient in js years

Silenced Ego02:08:30

As a newly grad, multi-lingual programmer with some self taught knowledge in clojure, how difficult is it to find a job in clojure in USA?

hamid tsh11:08:13

hi. i create a websocket using http-kit as a server side and use clojurescript as client-side. in clojurescript i have ( (set! (.-onmessage socket) (fn [msg] (js/console.log msg))) now when i print type of msg i get it's messageٍEvent. now how can i change this to string?

gklijs13:08:56

Needs another .-data (fn [msg] (js/console.log (.-data msg))) https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent#Properties

Ashley Smith13:08:37

So a while ago people helped me start learning about security and I followed this tutorial to get signed JWT tokens: https://funcool.github.io/buddy-auth/latest/#encrypted-jwt and the source code: https://github.com/funcool/buddy-auth/blob/master/examples/jwe/src/authexample/web.clj I have some more questions though. I have my server creating and giving out tokens to successfully authenticated users now, I understand that. But now, I need some help actually using the token, and I think in order to do that I need to learn what line 81 is fully doing.

(def secret (nonce/random-bytes 32))
...
;; Create an instance of auth backend.
(def auth-backend (jwe-backend {:secret secret
                                :options {:alg :a256kw :enc :a128gcm}}))
...
    (wrap-authorization $ auth-backend)
    (wrap-authentication $ auth-backend)
What exactly is secret? Its not a users password or anything, so I'm not quite sure how it fits. Secondly, auth-backend is wrapped around the handler, but I don't really know what A. The difference is between the authorization and authentication middleware, and how exactly these operate. There is a function called authenticated?, does the middleware handle the validation etc and then pass that result to this function as a bool for me to use? What if I want to know which user is authenticated etc? I'm struggling to follow the flow of the source code. I feel like im close but I just need a little push

lispyclouds13:08:23

@ashley Its a Nonce, mainly used initialize a crypto session. It needs to be random so that each session cannot be replayed. https://en.wikipedia.org/wiki/Cryptographic_nonce

Ashley Smith13:08:18

to put it bluntly, is a nonce kind of like a key in a cipher? And then you just use a new nonce each session to make sure people don't break the authentication barrier as easily?

lispyclouds13:08:00

so its to make a session unique, think of it as the initial seed to begin the crypto and the stuff following is generally a message that your gonna encrypt and are not so random

lispyclouds13:08:50

if the initial value of the ciper isnt random enough, its susceptible to https://en.wikipedia.org/wiki/Replay_attack

lispyclouds13:08:31

the key in the cipher is something that the user specifies like a password

Ashley Smith13:08:34

I'm learning! Thank you 🙂

lispyclouds13:08:29

Crypto is a world on its own, one never stops learning 😄

lispyclouds13:08:10

and for the wrapper, the ring middleware adds a Header to the response to which the client needs to present a valid token back

lispyclouds13:08:28

see https://jwt.io/introduction/ for more info. found this quite informative

Ashley Smith13:08:58

I wish my uni taught it

Ashley Smith13:08:04

so you wouldn't have to

Ashley Smith13:08:16

you wouldn't believe that im a final year computer science student

lispyclouds13:08:34

Well, most of the crypto stuff I picked up after college too. 😄

Ashley Smith14:08:19

(let [claims 
              { :usr (keyword username)
                :exp (time/plus (time/now) (time/seconds 3600))}
            token (jwt/sign claims secret {:alg :hs512})]
So after that site you showed me I understand this a lot better, the username is built into the token directly so that helps, and it also helps me place other items in it if I need to. The next thing I need to learn though is how to actually work with this token in code, as it's just a long string of characters. Should I be decoding this on clientside to get information like the userid or whatever?

Ashley Smith14:08:51

either way, I'll probably store it with re-frame or something, and then I just need to send it back with my requests

lispyclouds14:08:21

the authenticated? fn does the verification of the Authorized header

Ashley Smith14:08:47

I just need to learn how to actually put stuff in that header

lispyclouds14:08:49

verifies that the token sent by the client is a valid one

lispyclouds14:08:23

you want to know how to respond to the server from the client?

Ashley Smith14:08:27

(defn- make-http-get-request
  "Creates a HTTP-GET request"
  [uri on-success on-fail]
  { :method           :get
    :uri              (str "" uri)
    :timeout          8000
    :response-format  (ajax/json-response-format {:keywords? true})
    :on-success       [on-success]
    :on-failure       [on-fail]})
Would the token be inserted somewhere here I imagine?

lispyclouds14:08:15

what lib are you using on the frontend?

lispyclouds14:08:24

to make the request?

lispyclouds14:08:45

you basically need to add a header called Authorization having the value Token <the token here> <- the whole thing including the space after the Token needs to be the value of the header

Ashley Smith14:08:28

oh I thought that was pseudocode, my bad

Ashley Smith14:08:33

I didn't take it literally

Ashley Smith14:08:01

I'm using re-frame.http-fx

Ashley Smith14:08:30

so let me go dive into the docs and find out how to make that header

lispyclouds14:08:52

yeah, im not too familiar with that lib, im looking it up too

Ashley Smith14:08:08

out of interest, what do you use? 🙂

lispyclouds14:08:11

it looks like you can just have a key called :headers

lispyclouds14:08:30

and the value [:Authorization token]

Ashley Smith14:08:31

ah you beat me to it I just found it

lispyclouds14:08:21

the token could be (str "Token " token-from-server)

lispyclouds14:08:27

> out of interest, what do you use? To be honest I'm not much of a frontend person, just know enough to get it going. Mostly servers and infrastructure and yes being in Berlin, some amount of crypto and security too 😛

Ashley Smith14:08:18

im just learning so I'm going about the whole thing

Ashley Smith14:08:35

I kind of think I'd prefer to do backend, but I also think I'm not good enough yet 😛

lispyclouds14:08:58

Happy to help 😄

gerred14:08:06

what's the current state of the art wrt Clojure web servers? immutant and http-kit look great, especially doing websockets, but look untouched in a while. is that because they are stable or abandoned? should I be looking at jetty instead?

gerred15:08:02

i'm thinking I'm going to go with ring-jetty since it looks the most maintained

Jamie Rumbelow16:08:33

Hi all! I’m getting quite frustrated with clojure.java.jdbc; for instance, empty queries throwing an exception. I’m used to less low-level DB layers (am formerly a Laravel developer). I’m enjoying using HoneySQL to generate queries; what sort of layers of abstraction exist for executing them?

schmee17:08:50

you could try https://github.com/seancorfield/next-jdbc, it’s the successor to clojure.java.jdbc which is much improved, but equally low-level

schmee17:08:28

as for higher-level stuff the only two I’m aware of are https://github.com/metabase/toucan and https://github.com/walkable-server/walkable, and I haven’t used either so I can’t vouch for them

Jamie Rumbelow18:08:52

good starting point – thank you!

dharrigan19:08:07

I use next jdbc with honeysql and it's been great so far

👍 4
tdantas16:08:41

hey guys, I’m trying to create my own flatten function ( improve my clojure skills )

(defn my-own-flatten [tree]
  (loop [[h & t] tree
         result []]
     (cond
       (nil? h) result
       (coll? h) (recur h result)
       :else (recur t (conj result h)))))
the function is not working as expected, could you guys give me a hand ?

tdantas16:08:19

fixed my function

(defn my-own-flatten [tree]
  (loop [[h & t] tree
         result []]
     (cond
       (nil? h) result
       (coll? h) (recur t (doall (concat result (my-own-flatten h))))
       :else (recur t (doall (concat result [h]))))))

zonkhead18:08:32

Curious: why are you using doall? That's for controlling side-effects.

Ashley Smith23:08:14

Hey everyone! I need some help implementing the following in reagent with JS interop: https://github.com/sparksuite/simplemde-markdown-editor

<script>
var simplemde = new SimpleMDE({ element: document.getElementById("MyID") });
</script>
Here's my crack at it, but I can't even get the element itself to print - whenever I involve the SimpleMDE code I get TypeError: e is undefined
[:textarea#foo.textarea]
    (println (.getElementById js/document "foo"))
    ;(js/SimpleMDE. {"element" (.getElementById js/document "foo")})

David Pham23:08:03

You could convert the Clojure map to js with clj->js

David Pham23:08:59

Or use #js before your map to indicate that the following map is a JavaScript map

Ashley Smith23:08:13

@neo2551 even the (println line returns nil so I don't know really where I'm going wrong

Ashley Smith23:08:22

thanks for trying to help though as I'm out of ideas really

David Pham23:08:12

Did you create the page and tested the JavaScript command in the google console?

Ashley Smith23:08:24

no, that is a good shout!

Ashley Smith23:08:16

It works in the console

Ashley Smith23:08:23

so I just need to learn how to do it in clojure

Ashley Smith23:08:51

does the textarea actually exist by that println statement?

David Pham23:08:52

Actually no I don’t think so

David Pham23:08:03

I would first make sure your component is mounted

David Pham23:08:11

And then in the repl test your commands

Ashley Smith23:08:31

what do you mean by mounted? Sorry I'm not sure of the technicals of all this 😞

David Pham23:08:41

Reagent is a wrapper around react, so we use react life cycles methods in the background (the third form of components of reagent is about defining the whole life cycles)

David Pham23:08:23

To answer: mounted means that your components has been included/attached to your actual DOM (ie you can see it in the source file)

David Pham23:08:57

[disclamer: I learned reagent/cljs 6 months ago]

Ashley Smith23:08:07

this is the first time I've had to do this, I guess because I've never needed to get something by ID after it's in the DOM

Ashley Smith23:08:16

thank you for bringing this up, I'll keep reading

Ashley Smith23:08:26

maybe its just too late for me though I'm tired

David Pham23:08:32

So, to help you: first make a simple 1 form component with reagent with an idea

David Pham23:08:48

Then try to get it from your dev console in your browser in JavaScript

David Pham23:08:02

And then try to reproduce the step in your repl in cljs

David Pham23:08:03

Then write a function out of it. My guess is you will need to use a reagent/atom to store the state. I usually deal with that by using re-frame events and database

Ashley Smith23:08:03

yeah re-frame is great

David Pham23:08:03

This article is interesting as well

Ashley Smith23:08:12

I just didn't think it'd be so hard to do something like this tbh

David Pham23:08:22

Actually the reason is your trying to grab the value while your component is not even created yet. So it is normal that your compiler is unhappy :)

David Pham23:08:08

I am still a beginner, but I can tell you it gets easier quickly.

Ashley Smith23:08:55

it means a lot that you're trying!

David Pham23:08:11

(defn code-mirror []
  (reagent/create-class
    {:component-did-mount
     (fn [comp]
      (js/CodeMirror. (reagent/dom-node comp)))
     :reagent-render
     (fn []
       [:div])})) ;; this div will get returned by `dom-node` above

David Pham23:08:17

Change the reagent-render function to your hiccup vector and the :component-did-mount function to your JavaScript calls

David Pham23:08:30

Or use the node directly