When I test my POST route for Django Rest Framework API it returns a 401 not authenticated even though logged...











up vote
0
down vote

favorite












When I attempt to test my Create/POST route for my Django Rest Framework API I receive a response status code of 401 with the error detail telling me ErrorDetail(string=u'Authentication credentials were not provided.', code=u'not_authenticated'). The weird thing is I Django tells me I'm authenticated when I check is is_authenticated.



Does anyone have an idea what might be causing this? All relevant code provided below.



# test_api.py

def authorise_user_and_test_is_authenticated(self, user_id):
"""
Log in user and test this is successful
"""
user = User.objects.get(pk=user_id)
self.client.login(username=user.username, password=user.password)
authorised_user = auth.get_user(self.client)
return self.assertTrue(user.is_authenticated())

def test_create_project(self):
'''
When given valid parameters a project is created.
'''
user = User.objects.get(username="user_001")
self.authorise_user_and_test_is_authenticated(user.id) # pass of authenication and auth testing to method, when tested with is_authenicated() it returns true.

response = self.client.post('/api/user/{0}/project/create/'.format(user.id),
json.dumps({"model_name": "POSTed Project",
"description": "Project tested by posting",
"shared_users": [2]
}),
content_type='application/json')

self.assertEqual(response.status_code, 201)




# views.py

class MyCreateView(generics.GenericAPIView):
pass
serializer_class = FerronPageCreateAndUpdateSerializer

def get_queryset(self):
return User.objects.filter(pk=self.kwargs.get('user'))

def post(self, request, format=None, **kwargs):
# This dictionary is used to ensure that the last_modified_by field is always updated on post to be the current user
print request.data
request_data = {
'user': request.user.id,
'model_name': request.data['model_name'],
'description': request.data['description'],
'last_modified_by': request.user.id,
'shared_users': request.data.getlist('shared_users', )
}
serializer = FerronPageCreateAndUpdateSerializer(data=request_data)

if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)




# settings.py

REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication'
),
}




# url matcher

url(r'^user/(?P<user>d+)/project/create/$', MyCreateView.as_view(), name='create-project')




class FerronPageCreateAndUpdateSerializer(serializers.ModelSerializer):
shared_users = serializers.PrimaryKeyRelatedField(many=True, queryset=User.objects.all(), read_only=False)
description = serializers.CharField(max_length=300, trim_whitespace=True, required=False, allow_blank=True)

class Meta:
model = Project
fields = [
'pk',
'user',
'data',
'model_name',
'description',
'created_at',
'date_modified',
'shared_users',
'last_modified_by'


]










share|improve this question
























  • does the view working with normal API requests?
    – JPG
    Oct 28 at 2:13










  • rest does not have state .... you should auth another way (ie tokens attached to req) ... but basically that client was not authenticated...
    – Joran Beasley
    Oct 28 at 2:13












  • Hi Todd! Are you only having problems in the test? Either way the first step would be to remove pass from the first line after the MyCreateView class declaration. Next is to share the self.authorise_user_and_test_is_authenticated method or the whole test class if you can. Authentication in tests can be a pain so I've found using self.client.force_authenticate(user=user) in DRF tests to be an easy work around.
    – Jacob Harding
    Oct 28 at 5:12










  • Thanks all for your feedback so quickly. @JPG this works with normal api requests. @joran I had tried to access auth_token via user.auth_token but the key wasn't recognised? I'm not 100% sure on how to set that up.
    – Todd Drinkwater
    Oct 28 at 5:52










  • @JacobHarding Yes it only gives me problems during the test. However, when I've testing been doing get requests via the API that works fine. Have edited my question to include theself.authorise_user_and_test_is_authenticated method now. I tried force_authenticate but seem my post seems to still return a 401.
    – Todd Drinkwater
    Oct 28 at 5:56















up vote
0
down vote

favorite












When I attempt to test my Create/POST route for my Django Rest Framework API I receive a response status code of 401 with the error detail telling me ErrorDetail(string=u'Authentication credentials were not provided.', code=u'not_authenticated'). The weird thing is I Django tells me I'm authenticated when I check is is_authenticated.



Does anyone have an idea what might be causing this? All relevant code provided below.



# test_api.py

def authorise_user_and_test_is_authenticated(self, user_id):
"""
Log in user and test this is successful
"""
user = User.objects.get(pk=user_id)
self.client.login(username=user.username, password=user.password)
authorised_user = auth.get_user(self.client)
return self.assertTrue(user.is_authenticated())

def test_create_project(self):
'''
When given valid parameters a project is created.
'''
user = User.objects.get(username="user_001")
self.authorise_user_and_test_is_authenticated(user.id) # pass of authenication and auth testing to method, when tested with is_authenicated() it returns true.

response = self.client.post('/api/user/{0}/project/create/'.format(user.id),
json.dumps({"model_name": "POSTed Project",
"description": "Project tested by posting",
"shared_users": [2]
}),
content_type='application/json')

self.assertEqual(response.status_code, 201)




# views.py

class MyCreateView(generics.GenericAPIView):
pass
serializer_class = FerronPageCreateAndUpdateSerializer

def get_queryset(self):
return User.objects.filter(pk=self.kwargs.get('user'))

def post(self, request, format=None, **kwargs):
# This dictionary is used to ensure that the last_modified_by field is always updated on post to be the current user
print request.data
request_data = {
'user': request.user.id,
'model_name': request.data['model_name'],
'description': request.data['description'],
'last_modified_by': request.user.id,
'shared_users': request.data.getlist('shared_users', )
}
serializer = FerronPageCreateAndUpdateSerializer(data=request_data)

if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)




# settings.py

REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication'
),
}




# url matcher

url(r'^user/(?P<user>d+)/project/create/$', MyCreateView.as_view(), name='create-project')




class FerronPageCreateAndUpdateSerializer(serializers.ModelSerializer):
shared_users = serializers.PrimaryKeyRelatedField(many=True, queryset=User.objects.all(), read_only=False)
description = serializers.CharField(max_length=300, trim_whitespace=True, required=False, allow_blank=True)

class Meta:
model = Project
fields = [
'pk',
'user',
'data',
'model_name',
'description',
'created_at',
'date_modified',
'shared_users',
'last_modified_by'


]










share|improve this question
























  • does the view working with normal API requests?
    – JPG
    Oct 28 at 2:13










  • rest does not have state .... you should auth another way (ie tokens attached to req) ... but basically that client was not authenticated...
    – Joran Beasley
    Oct 28 at 2:13












  • Hi Todd! Are you only having problems in the test? Either way the first step would be to remove pass from the first line after the MyCreateView class declaration. Next is to share the self.authorise_user_and_test_is_authenticated method or the whole test class if you can. Authentication in tests can be a pain so I've found using self.client.force_authenticate(user=user) in DRF tests to be an easy work around.
    – Jacob Harding
    Oct 28 at 5:12










  • Thanks all for your feedback so quickly. @JPG this works with normal api requests. @joran I had tried to access auth_token via user.auth_token but the key wasn't recognised? I'm not 100% sure on how to set that up.
    – Todd Drinkwater
    Oct 28 at 5:52










  • @JacobHarding Yes it only gives me problems during the test. However, when I've testing been doing get requests via the API that works fine. Have edited my question to include theself.authorise_user_and_test_is_authenticated method now. I tried force_authenticate but seem my post seems to still return a 401.
    – Todd Drinkwater
    Oct 28 at 5:56













up vote
0
down vote

favorite









up vote
0
down vote

favorite











When I attempt to test my Create/POST route for my Django Rest Framework API I receive a response status code of 401 with the error detail telling me ErrorDetail(string=u'Authentication credentials were not provided.', code=u'not_authenticated'). The weird thing is I Django tells me I'm authenticated when I check is is_authenticated.



Does anyone have an idea what might be causing this? All relevant code provided below.



# test_api.py

def authorise_user_and_test_is_authenticated(self, user_id):
"""
Log in user and test this is successful
"""
user = User.objects.get(pk=user_id)
self.client.login(username=user.username, password=user.password)
authorised_user = auth.get_user(self.client)
return self.assertTrue(user.is_authenticated())

def test_create_project(self):
'''
When given valid parameters a project is created.
'''
user = User.objects.get(username="user_001")
self.authorise_user_and_test_is_authenticated(user.id) # pass of authenication and auth testing to method, when tested with is_authenicated() it returns true.

response = self.client.post('/api/user/{0}/project/create/'.format(user.id),
json.dumps({"model_name": "POSTed Project",
"description": "Project tested by posting",
"shared_users": [2]
}),
content_type='application/json')

self.assertEqual(response.status_code, 201)




# views.py

class MyCreateView(generics.GenericAPIView):
pass
serializer_class = FerronPageCreateAndUpdateSerializer

def get_queryset(self):
return User.objects.filter(pk=self.kwargs.get('user'))

def post(self, request, format=None, **kwargs):
# This dictionary is used to ensure that the last_modified_by field is always updated on post to be the current user
print request.data
request_data = {
'user': request.user.id,
'model_name': request.data['model_name'],
'description': request.data['description'],
'last_modified_by': request.user.id,
'shared_users': request.data.getlist('shared_users', )
}
serializer = FerronPageCreateAndUpdateSerializer(data=request_data)

if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)




# settings.py

REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication'
),
}




# url matcher

url(r'^user/(?P<user>d+)/project/create/$', MyCreateView.as_view(), name='create-project')




class FerronPageCreateAndUpdateSerializer(serializers.ModelSerializer):
shared_users = serializers.PrimaryKeyRelatedField(many=True, queryset=User.objects.all(), read_only=False)
description = serializers.CharField(max_length=300, trim_whitespace=True, required=False, allow_blank=True)

class Meta:
model = Project
fields = [
'pk',
'user',
'data',
'model_name',
'description',
'created_at',
'date_modified',
'shared_users',
'last_modified_by'


]










share|improve this question















When I attempt to test my Create/POST route for my Django Rest Framework API I receive a response status code of 401 with the error detail telling me ErrorDetail(string=u'Authentication credentials were not provided.', code=u'not_authenticated'). The weird thing is I Django tells me I'm authenticated when I check is is_authenticated.



Does anyone have an idea what might be causing this? All relevant code provided below.



# test_api.py

def authorise_user_and_test_is_authenticated(self, user_id):
"""
Log in user and test this is successful
"""
user = User.objects.get(pk=user_id)
self.client.login(username=user.username, password=user.password)
authorised_user = auth.get_user(self.client)
return self.assertTrue(user.is_authenticated())

def test_create_project(self):
'''
When given valid parameters a project is created.
'''
user = User.objects.get(username="user_001")
self.authorise_user_and_test_is_authenticated(user.id) # pass of authenication and auth testing to method, when tested with is_authenicated() it returns true.

response = self.client.post('/api/user/{0}/project/create/'.format(user.id),
json.dumps({"model_name": "POSTed Project",
"description": "Project tested by posting",
"shared_users": [2]
}),
content_type='application/json')

self.assertEqual(response.status_code, 201)




# views.py

class MyCreateView(generics.GenericAPIView):
pass
serializer_class = FerronPageCreateAndUpdateSerializer

def get_queryset(self):
return User.objects.filter(pk=self.kwargs.get('user'))

def post(self, request, format=None, **kwargs):
# This dictionary is used to ensure that the last_modified_by field is always updated on post to be the current user
print request.data
request_data = {
'user': request.user.id,
'model_name': request.data['model_name'],
'description': request.data['description'],
'last_modified_by': request.user.id,
'shared_users': request.data.getlist('shared_users', )
}
serializer = FerronPageCreateAndUpdateSerializer(data=request_data)

if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)




# settings.py

REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication'
),
}




# url matcher

url(r'^user/(?P<user>d+)/project/create/$', MyCreateView.as_view(), name='create-project')




class FerronPageCreateAndUpdateSerializer(serializers.ModelSerializer):
shared_users = serializers.PrimaryKeyRelatedField(many=True, queryset=User.objects.all(), read_only=False)
description = serializers.CharField(max_length=300, trim_whitespace=True, required=False, allow_blank=True)

class Meta:
model = Project
fields = [
'pk',
'user',
'data',
'model_name',
'description',
'created_at',
'date_modified',
'shared_users',
'last_modified_by'


]







python django django-rest-framework






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Oct 28 at 5:25

























asked Oct 28 at 2:09









Todd Drinkwater

5219




5219












  • does the view working with normal API requests?
    – JPG
    Oct 28 at 2:13










  • rest does not have state .... you should auth another way (ie tokens attached to req) ... but basically that client was not authenticated...
    – Joran Beasley
    Oct 28 at 2:13












  • Hi Todd! Are you only having problems in the test? Either way the first step would be to remove pass from the first line after the MyCreateView class declaration. Next is to share the self.authorise_user_and_test_is_authenticated method or the whole test class if you can. Authentication in tests can be a pain so I've found using self.client.force_authenticate(user=user) in DRF tests to be an easy work around.
    – Jacob Harding
    Oct 28 at 5:12










  • Thanks all for your feedback so quickly. @JPG this works with normal api requests. @joran I had tried to access auth_token via user.auth_token but the key wasn't recognised? I'm not 100% sure on how to set that up.
    – Todd Drinkwater
    Oct 28 at 5:52










  • @JacobHarding Yes it only gives me problems during the test. However, when I've testing been doing get requests via the API that works fine. Have edited my question to include theself.authorise_user_and_test_is_authenticated method now. I tried force_authenticate but seem my post seems to still return a 401.
    – Todd Drinkwater
    Oct 28 at 5:56


















  • does the view working with normal API requests?
    – JPG
    Oct 28 at 2:13










  • rest does not have state .... you should auth another way (ie tokens attached to req) ... but basically that client was not authenticated...
    – Joran Beasley
    Oct 28 at 2:13












  • Hi Todd! Are you only having problems in the test? Either way the first step would be to remove pass from the first line after the MyCreateView class declaration. Next is to share the self.authorise_user_and_test_is_authenticated method or the whole test class if you can. Authentication in tests can be a pain so I've found using self.client.force_authenticate(user=user) in DRF tests to be an easy work around.
    – Jacob Harding
    Oct 28 at 5:12










  • Thanks all for your feedback so quickly. @JPG this works with normal api requests. @joran I had tried to access auth_token via user.auth_token but the key wasn't recognised? I'm not 100% sure on how to set that up.
    – Todd Drinkwater
    Oct 28 at 5:52










  • @JacobHarding Yes it only gives me problems during the test. However, when I've testing been doing get requests via the API that works fine. Have edited my question to include theself.authorise_user_and_test_is_authenticated method now. I tried force_authenticate but seem my post seems to still return a 401.
    – Todd Drinkwater
    Oct 28 at 5:56
















does the view working with normal API requests?
– JPG
Oct 28 at 2:13




does the view working with normal API requests?
– JPG
Oct 28 at 2:13












rest does not have state .... you should auth another way (ie tokens attached to req) ... but basically that client was not authenticated...
– Joran Beasley
Oct 28 at 2:13






rest does not have state .... you should auth another way (ie tokens attached to req) ... but basically that client was not authenticated...
– Joran Beasley
Oct 28 at 2:13














Hi Todd! Are you only having problems in the test? Either way the first step would be to remove pass from the first line after the MyCreateView class declaration. Next is to share the self.authorise_user_and_test_is_authenticated method or the whole test class if you can. Authentication in tests can be a pain so I've found using self.client.force_authenticate(user=user) in DRF tests to be an easy work around.
– Jacob Harding
Oct 28 at 5:12




Hi Todd! Are you only having problems in the test? Either way the first step would be to remove pass from the first line after the MyCreateView class declaration. Next is to share the self.authorise_user_and_test_is_authenticated method or the whole test class if you can. Authentication in tests can be a pain so I've found using self.client.force_authenticate(user=user) in DRF tests to be an easy work around.
– Jacob Harding
Oct 28 at 5:12












Thanks all for your feedback so quickly. @JPG this works with normal api requests. @joran I had tried to access auth_token via user.auth_token but the key wasn't recognised? I'm not 100% sure on how to set that up.
– Todd Drinkwater
Oct 28 at 5:52




Thanks all for your feedback so quickly. @JPG this works with normal api requests. @joran I had tried to access auth_token via user.auth_token but the key wasn't recognised? I'm not 100% sure on how to set that up.
– Todd Drinkwater
Oct 28 at 5:52












@JacobHarding Yes it only gives me problems during the test. However, when I've testing been doing get requests via the API that works fine. Have edited my question to include theself.authorise_user_and_test_is_authenticated method now. I tried force_authenticate but seem my post seems to still return a 401.
– Todd Drinkwater
Oct 28 at 5:56




@JacobHarding Yes it only gives me problems during the test. However, when I've testing been doing get requests via the API that works fine. Have edited my question to include theself.authorise_user_and_test_is_authenticated method now. I tried force_authenticate but seem my post seems to still return a 401.
– Todd Drinkwater
Oct 28 at 5:56












1 Answer
1






active

oldest

votes

















up vote
0
down vote













Turn's out the issue was here self.client.login(username=user.username, password=user.password) inside the authorise_user_and_test_is_authenticated(self, user_id) method.



The problem was that I was using the password an instance of a user I had already created. This meant when I gave the argument password=user.password, I was trying to log in using a password that had already been hashed. What I needed to do instead was log in with the original unhashed version of the password e.g. password='openseasame'.






share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53027815%2fwhen-i-test-my-post-route-for-django-rest-framework-api-it-returns-a-401-not-aut%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    0
    down vote













    Turn's out the issue was here self.client.login(username=user.username, password=user.password) inside the authorise_user_and_test_is_authenticated(self, user_id) method.



    The problem was that I was using the password an instance of a user I had already created. This meant when I gave the argument password=user.password, I was trying to log in using a password that had already been hashed. What I needed to do instead was log in with the original unhashed version of the password e.g. password='openseasame'.






    share|improve this answer

























      up vote
      0
      down vote













      Turn's out the issue was here self.client.login(username=user.username, password=user.password) inside the authorise_user_and_test_is_authenticated(self, user_id) method.



      The problem was that I was using the password an instance of a user I had already created. This meant when I gave the argument password=user.password, I was trying to log in using a password that had already been hashed. What I needed to do instead was log in with the original unhashed version of the password e.g. password='openseasame'.






      share|improve this answer























        up vote
        0
        down vote










        up vote
        0
        down vote









        Turn's out the issue was here self.client.login(username=user.username, password=user.password) inside the authorise_user_and_test_is_authenticated(self, user_id) method.



        The problem was that I was using the password an instance of a user I had already created. This meant when I gave the argument password=user.password, I was trying to log in using a password that had already been hashed. What I needed to do instead was log in with the original unhashed version of the password e.g. password='openseasame'.






        share|improve this answer












        Turn's out the issue was here self.client.login(username=user.username, password=user.password) inside the authorise_user_and_test_is_authenticated(self, user_id) method.



        The problem was that I was using the password an instance of a user I had already created. This meant when I gave the argument password=user.password, I was trying to log in using a password that had already been hashed. What I needed to do instead was log in with the original unhashed version of the password e.g. password='openseasame'.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 11 at 9:03









        Todd Drinkwater

        5219




        5219






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53027815%2fwhen-i-test-my-post-route-for-django-rest-framework-api-it-returns-a-401-not-aut%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Guess what letter conforming each word

            Port of Spain

            Run scheduled task as local user group (not BUILTIN)