Thread safety in rails with slack-api gem - ruby-on-rails

I have just started using rails. In my app I have to access Slack apis, so I am using the slack-api gem. The way to configure that is
Slack.configure do |config|
config.token = "token"
end
I am wondering since the token is configured at class level 'Slack', would that cause any inconsistent behaviour? One request might set it to value A and before it is done, another request may set it to value B.

While Ruby web frameworks are generally single-threaded, this is not always the case. So it likely will cause problems if the token is different across multiple requests, will be hard to reason about or become a problem in the long run.
Try the newer gem, https://github.com/dblock/slack-ruby-client which will take a token in the initializer, ie. Slack::Web::Client.new(token: 'token') or Slack::RealTime::Client.new(token: 'token'), should avoid the problem altogether.

Related

JWT Authentication graphql-spqr with spring security

I am using graphql-spqr-spring-boot-starter, version 0.0.5 in my spring boot application.
#GraphQLApi & #GraphQLQuery working fine and I am fetching data on /gui as well.
But as many have faced I am trying to apply the authentication part on graphql server calls. I am using JWT token in my application for REST API authorization/authentication.
So I have token which I suppose can be used for validation here as well.
I have tried using:
#PreAuthorize("hasRole('ROLE_RECRUITER_HR')")
but it gives compile time error:
io.leangen.graphql.metadata.exceptions.TypeMappingException: The
registered object of type com.sun.proxy.$Proxy90 appears to be a
dynamically generated proxy
For these and other possible issues, is it better to use wrapper graphql library like spring-boot-starter or it is safer to use graphql-spqr which more steps in my hand.
EDIT: GraphQL SPQR Spring Boot starter v0.0.6 fixed the issue and should work out of the box.
This is a bug in the starter. It doesn't properly detect the types when JDK proxies (and not CGLib) are used. I will make sure to fix this for the next release.
There's a couple of ways to temporarily work around this, but none of them are nice unfortunately.
You could e.g. force Spring to use CGLIB by e.g.
#EnableAspectJAutoProxy(proxyTargetClass = true)
but this has potentially wide implications so I would recommend you simply wait a bit. I'll release a new version with a fix in a couple of days, as this is a very important bug.

Is there a canonical pattern for caching something related to a session on the server?

In my Rails app, once per user session, I need to have my server send a request to one of our other services to get some data about the user. I only want to make this request once per session because pinging another service every time the user makes a request will significantly slow down our response time. However, I can't store this information in a cookie client-side. This information has some security implications - if the user has the ability to lie to our server about what this piece of information is, they can gain access to data they're not authorized to see.
So what is the best way to cache or store a piece of data associated with a session on the Rails server?
I'm considering using Rails low-level caching, and I think it might even be correct:
Rails.cache.fetch(session.id, expires_in: 12.hours) do
OtherServiceAPI.get_sensitive_data(user.id)
end
I know that Rails often has one canonical way of doing things, though, so I want to be sure there's not a built-in, officially preferred way to associate a piece of data with a session. This question makes it look like there are potential pitfalls using the approach I'm considering as well, although it looks like those concerns may have been made obsolete in newer versions of Rails.
Is there a canonical pattern for what I'm trying to do? Or is the approach I'm considering idiomatic enough?

How can I use VCR with Rails 5.1 system tests?

Many things on the web seem to suggest that VCR can be used with Capybara.
I have three problems.
This doesn't make much sense to me, because the test driver and the application code don't share memory.
I'm not finding full recipes on how to set this up.
I'm finding bits and pieces of how people have set this up, but it's outside of the context of rails 5.1, which does the capybara setup behind the scenes.
How do I configure a Rails 5.1 app, Capybara, and VCR to work together for system tests?
(My headless browser is phantomjs, driven by poltergeist. But I don't need to intercept requests from the browser, only server-side requests. If I needed to intercept from the browser I would probably use a full http proxy server, like puffing-billy.)
I'm assuming you mean Rails 5.1 since Rails 5 doesn't have system tests.
The copy of the application Capybara runs for testing is run in a separate thread, not a separate process. This means they do have access to the same memory, and loaded classes
There is nothing special required for configuring WebMock or VCR beyond what their READMEs already provide
The setup of Capybara and how Rails handles it is irrelevant to the configuration of WebMock or VCR. Additionally, even when using Rails 5.1 system tests all of the normal Capybara configuration options are still usable.
That all being said, there are a couple of things to be aware of here. Firstly, WebMock/VCR can only deal with requests made by your app (not from the browser which you stated you don't need) and it's generally better to use faked services (if possible) rather than WebMock/VCR when doing end to end system tests since there is less interference with the code under test.
If this doesn't answer your issues, post a question with a specific issue you're having, the code that's causing your issue, and the error you're getting.

Is it correct to store vcr cassettes in repository?

I develop a Ruby interface for one REST api. I use rspec and vcr for testing.
All tests use credentials of account, specially created for it.
I can't decide: is it correct to store cached responses of my tests(vcr cassettes) in
repository, or allow users and subscribers to write their own cassettes?
By the name of the Emperor! Let the Holy War begins!
VCR's cassettes play as the fixture of your tests. You do need to commit them into repository otherwise your tests won't run correctly in others' machine, or only correct there with heavy external dependency which is a violation of testing principle.
Of course you need to hide your credentials from public or team while keeping the above.
The solution is filter_senstive_data settings and Figaro gem.
At first, This answer from Myron in a similar question can solve your problem largely.
To setup VCR
VCR.configure do |c|
c.filter_sensitive_data("<SOMESITE_PASSWORD>") do
ENV['SOMESITE_PASSWORD']
end
end
The above block of code copied from Myron's answer because I want to add more later
For more about this setting, check the doc https://relishapp.com/vcr/vcr/v/2-5-0/docs/configuration/filter-sensitive-data
Now, for ENV['SOMESITE_PASSWORD'], it can be real credential by using Figaro gem.
Installation of Figaro will create a file config/application.yml and add it to .gitignore. So, you can just input your credential username and password there without risking leaking it to public.
As long as you aren't including any sensitive information in the requests then I see no reason why you can't commit them.
But as long as it will work fine after first test seeding the cassettes there isn't too much at stake either way.
Personally I like the idea of being checked against historical requests in case I have to diagnose some obscure machine-specific error changing my request formats. (IE some encoding bug where things are being escaped incorrectly due to a dynamically loaded library).

Rails + SSL: Per controller or application-wide?

I could use some wisdom from any developers who have worked with Rails and SSL. I have a fairly simple app and I'm in the process of implementing payment processing. Obviously payment processing calls for SSL, so I'm setting that up now.
My intention when I started working on this today was to find the simplest / cleanest way to enforce SSL on specific controller actions - namely anything having to do with payment. I figured there was no reason to run the rest of my site on SSL.
I found the ssl_requirement gem which seems to take care of setting SSL per-controller-action without much difficulty, so that's good. I also found this question which seems to indicate that handling SSL with a gem is now out-of-style.
I also found several answers / comments etc. suggesting that a site should just use Rack middleware like Rack-SSL to force the entire site to SSL mode.
So now I'm kind of confused, and not sure what I should do. Could anyone with experience working with Rails 3 and SSL help me understand:
Whether I should force the whole site to SSL, or only per certain actions.
What gotchas to look out for using SSL in Rails (I've never done it before).
If per-controller is the way to go, whether it makes sense to use the ssl-requirement gem or whether I should just use the new routing and link helper options...
I'd very much appreciate your insight, this has become a paralyzing decision for me. Thanks!
I've found myself "paralyzed" by this decision in the past, and here's what I think about each time.
First, keep in mind that some browsers will throw pop-up warnings if you keep switching out of and into SSL, or if you serve some content (the page) with SSL and other content (images, css) without. Obviously that's not a good experience for users.
The only possible downside to requiring SSL everywhere is performance. But unless you're expecting 1000+ users/day who will be doing lots of things that *don't * require SSL, this is negligible.
SSL is handled at the Apache/Nginx/whatever level. So if you decide to put your entire app behind SSL, it makes most sense to deal with it at the Webserver level (redirect http:/yoursite.com to https://yoursite.com.
And if, for performance reasons, you decide not to put everything behind SSL, then it still could make sense to handle SSL redirects at the Webserver level. Allowing your user through your Webserver, then sending him through half Rails stack, just to boot him back out to start over again is very wasteful.
Of course there's something to be said for simplicity and domains of knowledge, which would suggest handling redirects in your Rails app or middleware, since it "knows" what's safe and unsafe.
But those are things you'll have to weigh yourself. It depends on whether raw performance or simplicity of development/maintenance is more important.
I usually end up with a virtual host for http://mysite.com which redirects everything (or sometimes only certain uris) to https://mysite.com/$1. Hope that's helpful.

Resources