When I set default permission settings to
"DEFAULT_PERMISSION_CLASSES": [
"rest_framework.permissions.AllowAny",
],
and then define different permission for views like
#requires_csrf_token
#permission_classes([IsAuthenticated])
#api_view(["POST"])
def logout(request):
pass
I expected the view permission to be set as IsAuthenticated. But it behaves as AllowAny.
I'm using django rest simple JWT as authentication class.
The problem is that only the last decorator is applied, and others above, not working. Although I've not found solution for this problem yet.
As mentioned in the documentation, your #permission_classes decorator
must come after (below) the #api_view decorator
So I would rather try:
#requires_csrf_token
#api_view(["POST"])
#permission_classes([IsAuthenticated])
def logout(request):
pass
Related
I'm confused about factories.
#pytest.fixture
def a_api_request_factory():
return APIRequestFactory()
class TestUserProfileDetailView(TestCase):
def test_create_userprofile(self, up=a_user_profile, rf=a_api_request_factory):
"""creates an APIRequest and uses an instance of UserProfile from a_user_profile to test a view user_detail_view"""
request = rf().get('/api/userprofile/') # the problem line
request.user = up.user
response = userprofile_detail_view(request)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['user'], up.user.username)
if I take out the parens from rf().get.... then I get
"function doesn't have a get attribute".
If I call it directly then it gives me:
"Fixture "a_api_request_factory" called directly. Fixtures are not
meant to be called directly, but are created automatically when test
functions request them as parameters. See
https://docs.pytest.org/en/stable/fixture.html for more information
about fixtures, and
https://docs.pytest.org/en/stable/deprecations.html#calling-fixtures-directly
about how to update your code."
I do believe I've hit every combination of with or without parens in all relevant locations. Where do the parens go for fixtures?
Or better yet is there a pattern to avoid this type of confusion completely?
I have following index action in controller
def index
details = CustomerInfo.current
.for_user(params[:user])
.for_product(params[:product])
.for_area(params[:area])
.where(value: params.permit(:value))
render(json: details)
end
When i added permit in where i started getting the error can't quote ActionController::Parameters at render(json: details)
But if i not use permit .where(value: params[:value]) it works fine.
I don't think you are using permit as it's intended to be used.
params.permit returns an instance of ActionController::Parameters, hence the error you get. See here for the code.
permit should be used to limit the attributes that can be updated through mass assignment.
Here's the relevant documentation for it: https://apidock.com/rails/ActionController/Parameters/permit
http://guides.rubyonrails.org/action_controller_overview.html#strong-parameters
I'm working on an app that uses state_machine. I want to call a transition method but not persist the change, so that I have an opportunity to check whether the proposed change is authorized. Eg:
def some_controller_action
# ...
account.close # but don't save...
authorize account # will explode if current_user may not do this
if account.save ....
How can I do this?
Pass false
Eg:
account.close(false) # does not save
This isn't exactly documented, but I found it here.
I want all users to be authenticated before accessing my application. Following is the setting in Config.groovy:
grails.plugin.springsecurity.controllerAnnotations.staticRules=[
"/**": ["ROLE_ADMIN"],
"/login/auth": ["permitAll"]
]
The reason I put "/login/auth": ["permitAll"] is that any user can have a chance to log in and be authenticated. However, when I access http://localhost:8080/myapp/, it redirects to http://localhost:8080/myapp/login/auth and throws the error: The page isn't redirecting properly. Can you please advise what mistake I have committed here?
For first you must say to spring security what type of mapping you will be use.
grails.plugins.springsecurity.securityConfigType = 'InterceptUrlMap'
For second 'permitAll' changed to 'IS_AUTHENTICATED_ANONYMOUSLY'
And for third, if spring security find /** he didn't see another under this line. So your code must be like this:
grails.plugins.springsecurity.securityConfigType = SecurityConfigType.InterceptUrlMap
grails.plugins.springsecurity.interceptUrlMap = [
"/login/auth": ["permitAll"],
"/**": ["ROLE_ADMIN"]
]
TrongBang and Koloritnij are on the right track. But they're not completely correct in the context of your question. They're suggesting that you switch to a different authentication setup. (Which that will work but it doesn't solve the problem in the context of your setup.)
If you wish to keep the annotations, you're going to have to call out the controller that OAuth uses.
‘/springSecurityOAuth/**’: [‘permitAll’]
The plugin maps that controller path, but the static rules still interprets the controller and methods from that.
This took some digging for me to find this out. I had your same issue, and I blogged about this (and it includes some of the details about how the Spring Security Oauth plugin works.
http://theexceptioncatcher.com/blog/2015/04/spring-security-oauth-the-missing-instructions/
The solution from Koloritnij is correct. However, it threw the following error when using SecurityConfigType.InterceptUrlMap:
ERROR: the 'securityConfigType' property must be one of
'Annotation', 'Requestmap', or 'InterceptUrlMap' or left unspecified
to default to 'Annotation'; setting value to 'Annotation'
I have changed it to 'InterceptUrlMap' only and it worked:
grails.plugins.springsecurity.securityConfigType = 'InterceptUrlMap'
grails.plugins.springsecurity.interceptUrlMap = [
"/login/auth": ["permitAll"],
"/**": ["ROLE_ADMIN"]
]
I can't seem to set up a custom URL. All the RESTful routes work fine, but I can't figure out how to simply add /:unique_url to the existing routes, which I create in the model (a simple 4 character random string) and will serve as the "permalink" of sorts.
Routes.rb
resources :treks
match ':unique_url' => 'treks#mobile'
Controller
.
.
def mobile
#trek = trek.find(params[:id])
end
Is this because I'm trying to define a custom action on an existing resource? Can I not create custom methods on the same controller as one with a resource?
By the way, when I change routes.rb to match 'treks/:id/:unique_url' => treks#mobile it works fine, but I just want the url to simply be /:unique_url
Update It seems like find_by_[parameter] is the way to go...
I've been playing in console and I can't seem to get any methods to come forward...I can run Trek.last.fullname for example, but cannot run #trek = Trek.last...and then call...#trek.lastname for example. Any clues why? I think this is my issue.
So is there a field on Trek which stores its unique url? If so you should be doing something like this:
#trek = Trek.find_by_url(params[:unique_url])
trek.find_by_unique_url( params[:unique_url] ) # should do the trick
#pruett no, the find_by_XXX methods are generated on-the-fly via Ruby's method_missing call! So instead of XXX you can use any of the attributes which you defined in a model.
You can even go as far as listing multiple attributes, such as:
find_by_name_and_unique_url( the_name, the_unigue_url)
Check these pages:
http://guides.rubyonrails.org/active_record_querying.html
http://m.onkey.org/active-record-query-interface
if you get a undefined method ... for nil:NilClass , it means that the object you are trying to call that method on does not exist, e.g. is nil.
You probably just missed to put an if-statement before that line to make sure the object is non-nil
Hmm. I usually would do something like this:
map.connect "/:unique_url", :controller => "treks", :action => "mobile"
Then in that controller the ID isn't going to be applicable.. you'd need to change it to something like this:
def mobile
#trek = trek.find_by_unique_url(params[:unique_url])
end
(that's if unique_url is the column to search under)