django-rest-auth: how to get user info after successful authentication? - django-rest-auth

The django-rest-auth returns a token after successful authentication using rest_auth.serializers.TokenSerializer. How can I override this serializer or add my own so that I can get the user info like username, instead of token key after successful authentication?

I solved the problem by defining a custom serializer.
from django.contrib.auth.models import User
from rest_framework import serializers
from rest_auth.models import TokenModel
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'email')
class TokenSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = TokenModel
fields = ('key', 'user')
You can also use the depth option to easily generate nested representations, but in that case, you will receive the password field as well, which is not expected and intended.

Related

Remove authentication and permission classes only on one action

I have a generic view set custom action and i want to remove only from this action the authentication and permission classes. I tried the following but it does not work.
class ExampleView(GenericViewSet,
mixins.ListModelMixin,
mixins.DestroyModelMixin,
mixins.CreateModelMixin,
):
authentication_classes = [SessionAuthentication, BasicAuthentication]
permission_classes = [IsAuthenticated]
def custom_action(self, request, format=None):
self.authentication_classes = []
self.permission_classes = []
When you mark the custom action for routing with the action decorator, you should be able to specify the permission classes and authentication classes.
For example:
class ExampleView(GenericViewSet,
mixins.ListModelMixin,
mixins.DestroyModelMixin,
mixins.CreateModelMixin,
):
authentication_classes = [SessionAuthentication, BasicAuthentication]
permission_classes = [IsAuthenticated]
#action(detail=False, permission_classes=[AllowAny], authentication_classes=[])
def custom_action(self, request, format=None):
...

Django Rest Framework nested serialization validators

Is there a way to bypass Django Rest Framework validators in nested serialization without overwriting the validators on the original serializers?
Example :
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username')
class TaskSerializer(serializers.ModelSerializer):
owner = UserSerializer()
class Meta:
model = models.Task
If I try to update or create a Task I'll get a unicity error, because DRF use the unique constraint on the username field of the User model.
The solution I have found is to overwrite the validators on the UserSerializer:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username')
extra_kwargs = {
'username': {
'validators': []
}
Is there a way to bypass this validation without overwriting the validators directly in the UserSerializer?
By overwriting this validator I have to rewrite every constraints that I defined on my model.
A solution like below would have been nice, since it would have allow to bypass the validators only in the TaskSerializer without overwriting the initial UserSerializer.
class TaskSerializer(serializers.ModelSerializer):
owner = UserSerializer(validators=[])
class Meta:
model = models.Task

Creating a unique Id and saving it in DB

I am new to Spring REST. I have to achieve the below mentioned requirement using Spring REST. I have to use JPA Repository for DB interaction
I have 2 tables, Application and App_Config. Application table has the following rows:
id(Primary Key), ApplicationId, Status, Source_System. App_config table has the following rows: ApplicationId (foreign key), HeaderText, FooterText. I need to use java UUID to generate a unique id for the application every time a new application sends an HTTP POST request. Based on the ApplicationId generated I need to save the data in App_Config table. There is a possibility that the same application appears twice. In that case I have to retrieve the already generated ApplicationId and load the Header and Footer from App_Config table.
Please advise how to achieve this via POST method. I need to send back only the generated ApplicationId to the user
Partial solution of your problem (the other part is not understood) regarding sending a rest with UUID and the rest api will be server+/generator/uuid
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;
#RestController
#RequestMapping("/generator")
public class UuidGeneratorRestController {
#RequestMapping(value = "/uuid", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<UUID> getUUID() {
UUID generated = UUID.randomUUID();
return new ResponseEntity(generated, HttpStatus.OK);
}
}

DRF 3.0: Sharing a single UniqueTogetherValidator among related Serializers with Django Rest Framework

I’m dealing with a set of Model classes which share some common attributes via inheritance:
class MyBaseModel(models.Model):
class Meta:
abstract = True
unique_together = (('system', 'code',),)
id = models.UUIDField(default=uuid.uuid4, primary_key=True, unique=True, ...
system = models.ForeignKey(System, ...
code = models.CharField(...
...
class ModelA(MyBaseModel):
...
class ModelB(MyBaseModel):
...
Please note the presence of a unique_together constraint in Meta class.
A similar hierarchy would be convenient for the corresponding serializers;
I'm not sure whether I need to explicitly specify a UniqueTogetherValidator,
and currently investigating on this.
But in case, I wonder how to express it in the base serializer class, as it
requires a queryset which is not known in advance:
from rest_framework import serializers
from rest_framework.validators import UniqueTogetherValidator
class MyBaseModelSerializer(serializers.ModelSerializer):
class Meta:
exclude = ['date_created', 'created_by', ...
validators = [
UniqueTogetherValidator(
queryset=???.objects.all(),
fields=('system', 'code')
)
]
class ModelASerializer(MyBaseModelSerializer):
class Meta(MyBaseModelSerializer.Meta):
model = ModelA
...
class ModelBSerializer(MyBaseModelSerializer):
class Meta(MyBaseModelSerializer.Meta):
model = ModelB
...
How can I avoid repeating it for every single derived class, as in the following
example ?
from rest_framework import serializers
from rest_framework.validators import UniqueTogetherValidator
class MyBaseModelSerializer(serializers.ModelSerializer):
class Meta:
exclude = ['date_created', 'created_by', ...
class ModelASerializer(MyBaseModelSerializer):
class Meta(MyBaseModelSerializer.Meta):
model = ModelA
validators = [
UniqueTogetherValidator(
queryset=ModelA.objects.all(),
fields=('system', 'code')
)
]
...
class ModelBSerializer(MyBaseModelSerializer):
class Meta(MyBaseModelSerializer.Meta):
model = ModelB
validators = [
UniqueTogetherValidator(
queryset=ModelB.objects.all(),
fields=('system', 'code')
)
]
...
Model Serializer adds the UniqueTogetherValidator from model's unique_together constraints. You don't have give seperately.
need override
unique_together = (('system', 'code',),)
in non abstract model

How to get custom User object from AuthenticationFailureBadCredentialsEvent / AuthenticationSuccessEvent object

I'm trying to show no of invalid attempts of user using spring security.I'm using a custom User class to get additional user details other than username and password. I've created two listener classes i.e. AuthenticationSuccessEventListener & AuthenticationFailureListener to update user's invalid attempts.
Now in the onApplicationEvent method i'm trying to get custom User object (CustomUserDetails) like shown below:
#Component
public class AuthenticationFailureListener implements ApplicationListener<AuthenticationFailureBadCredentialsEvent> {
#Autowired
private ILoginDAO loginDAO ;
#Override
public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent event) {
CustomUserDetails user = (CustomUserDetails)event.getAuthentication().getPrincipal();//I get ClassCastException here.
String strUserID = user.getUserID();
CustomUserDetails customUser = loginDAO.loadUserByUsername(strUserID);
if (customUser != null){
...
} } }
event.getAuthentication().getPrincipal() returns a String i.e. username which i'm trying to cast it to CustomUserDetails (custom User class) and i get error.
P.S - I'm entering userid/password in login page and hence i pass userid as parameter for all the methods including loadUserByUsername(strUserID).
How can i get my custom User object in the listener class from AuthenticationFailureBadCredentialsEvent / AuthenticationSuccessEvent object?
The event just contains the authentication request object, i.e. the Authentication which was passed to the AuthenticationManager and which failed. So it will contain the submitted username as the principal.
Authentication may have failed for a variety of reasons, including a non-existent username, and in fact doesn't even need to involve a UserDetails object at all, so if you want the full information you will need to load it using the username.
Alternatively you could customize an AuthenticationProvider to perform the additional work you want in the implementation itself, rather than via an event.

Resources