401 "Unauthorized" error in Django and Angular File Upload - django

I have created a Django and Angular application to upload files. It was working without errors until I integrated a login page. I have not been able to upload files since integration. I get 401 - "Unauthorized" error. What could have possibly gone wrong?
Auth-interceptor:
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest,HttpErrorResponse } from "#angular/common/http";
import { Injectable } from "#angular/core";
import { catchError, Observable, throwError } from "rxjs";
import { LoginService } from "src/services/login.service";
#Injectable()
export class AuthInterceptorService implements HttpInterceptor {
constructor(private authService: LoginService) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (this.authService.isLoggedIn()) {
const token = this.authService.getAuthToken();
console.log("intercept",token)
// If we have a token, we set it to the header
request = request.clone({
setHeaders: {Authorization: `Token ${token}`}
});
}
return next.handle(request)
}
}
fileupload.component.ts:
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup } from '#angular/forms';
import { LoginService } from 'src/services/login.service';
import { FileUploader, FileLikeObject } from 'ng2-file-upload';
import { concat, Observable } from 'rxjs';
import { HttpEvent, HttpEventType } from '#angular/common/http';
#Component({
selector: 'app-fileupload',
templateUrl: './fileupload.component.html',
styleUrls: ['./fileupload.component.scss']
})
export class FileuploadComponent {
DJANGO_SERVER = 'http://127.0.0.1:8081'
public uploader: FileUploader = new FileUploader({});
public hasBaseDropZoneOver: boolean = false;
constructor(private formBuilder: FormBuilder, private uploadService: LoginService) { }
fileOverBase(event): void {
this.hasBaseDropZoneOver = event;
}
getFiles(): FileLikeObject[] {
return this.uploader.queue.map((fileItem) => {
return fileItem.file;
});
}
upload() {
let files = this.getFiles();
console.log(files);
let requests= [];
files.forEach((file) => {
let formData = new FormData();
formData.append('file' , file.rawFile, file.name);
requests.push(this.uploadService.upload(formData));
console.log(requests,file)
});
concat(...requests).subscribe(
(res) => {
console.log(res);
},
}
);
}}
console.log(err);
}
);
}}
service:
public upload(formData) {
let token= localStorage.getItem('token');
return this.http.post<any>(`${this.DJANGO_SERVER}/upload/`, formData).pipe(map((res) => {
console.log(res)
})
)
}
Thank you

I resolved the issue. It was because I was usign interceptor and I was using third party API for authentication. So instead of Django token, the third party APIs token was sent in header of POST request.
How I resolved it?
I used Httpbackend to process POST requests to Django DB so that the request is not intercepted and then I added custom header (with Django token to the reuest). I used the code snippet on this website: https://levelup.gitconnected.com/the-correct-way-to-make-api-requests-in-an-angular-application-22a079fe8413

Related

Angular app keeps saying message does not exist

I'm building a chat app with Angular and Django using the get stream tutorial. https://getstream.io/blog/realtime-chat-django-angular/
However, I'm trying to run the app to create the chat view but it keeps saying 'messages' does not exist at the point marked 'this point' in the code.
import { Component, OnInit } from '#angular/core';
import { Router } from '#angular/router';
import { MessageResponse, Channel } from 'stream-chat';
import { StreamService } from '../stream.service';
import { StateService } from '../state.service';
declare const feather: any;
#Component({
selector: 'app-chat',
templateUrl: './chat.component.html',
styleUrls: ['./chat.component.scss'],
})
export class ChatComponent implements OnInit {
constructor(
public streamService: StreamService,
private stateService: StateService,
private router: Router
) {}
messages: MessageResponse[] = [];
message = '';
channel!: Channel;
async sendMessage() {
if (this.message) {
try {
await this.channel.sendMessage({
text: this.message,
});
this.message = '';
} catch (err) {
console.log(err);
}
}
}
getClasses(userId: string): { outgoing: boolean; incoming: boolean } {
const userIdMatches = userId === this.streamService.currentUser.messages.id; (this point)
return {
outgoing: userIdMatches,
incoming: !userIdMatches,
};
}
}

Ionic 2: How to call Provider function in Controller class

I have created new Cordova Plugin only on my machine. Then I added it to my project. It is working fine when I call that plugin. Now, I tried to make a structured caller for my plugin. I created a Provider for it, but the problem is I don't know how to call my plugin function from my Controller class. Below is my sample code.
Provider: my-service.ts
import { Injectable } from '#angular/core';
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
declare let myPlugin: any;
#Injectable()
export class MyService {
constructor(public http: Http) {
console.log('Hello MyService Provider');
}
public myFunction() {
myPlugin.myPluginFunction(
(data) => {
return data;
},
(err) => {
return err;
});
}
}
Pages: my-page.ts
import { Component } from '#angular/core';
import { NavController, ViewController } from 'ionic-angular';
import { MyService } from '../../providers/my-service';
#Component({
selector: 'page-my-page-ionic',
templateUrl: 'hello-ionic.html'
})
export class MyPage {
constructor(private viewCtrl: ViewController, private myService: MyService) {}
ionViewWillEnter() {
//I tried to call like this
this.myService.myFunction().subscribe(
data => {
alert("success");
},
error => {
alert("error");
});
}
}
It returns me this error - Property 'subscribe' does not exist on type 'void'. I don't know how to call that function, since my provider returns me success or error.
I think since your myFunction() does not return any observable you cannot subscribe to it. It just returns data directly.
You can use it like this in this case:
var data = this.myService.myFunction();
console.log("Data from plugin is :", data);
If you want to use it as an Observable, return a new observable like this:
public myFunction() {
return Observable.create(observer => {
myPlugin.myPluginFunction(
(data) => {
observer.next(data);
},
(err) => {
observer.next(data);
});
},
(err) => {
observer.error(err);
});
}

How to write the post method in ionic?

I am new to the ionic framework,I had written the post call, I don't know exactly the post method.When i entered the submit button in forgot password page,if the user is already registered then should display the next page else it should display the alert message.
Below is my code:
import { Component } from '#angular/core';
import { configurator } from '../../providers/configurator';
import { NavController } from 'ionic-angular';
// import { LoginPage } from '../login/login';
import { persistence } from '../persistence/persistence';
#Component({
templateUrl: 'home.html'
})
export class home {
public loginId = "";
constructor(public navCtrl: NavController) {
}
generateOTP(newstate) {
console.log("invoking generateOTP FN");
var _this = this;
this.login.generateOTP(this.loginId, function(result,data){
if(result == '1') {
alert(data);
var a = document.createElement('a');
a.href="OTP page";
}
else {
//this.showRePasswd = this.showRePasswd;
alert(data);
}
})
}
}
This is my ionic-page:enter image description here
Can anyone help me!!!
my post belowed in IONIC2
import { Http, Response } from '#angular/http';
constructor(public navCtrl: NavController, private http: Http) { }
this.http.post(`${POST_URL}/log/add`, JSON.stringify(this.currentLocation), {headers})
.toPromise()
.then((response) => {
if (response.status !== 201) {
this.trace.error('log','postLog',`error response: ${response.status}`);
}
})
.catch(error => {
this.trace.error('log','postLog',`err post log:${error}`);
});

using MockBackend to test function that then calls .map

I am trying to write unit tests for my service which makes Http requests.
I have a service that returns a Http.get() request followed by a .map(). I am having trouble getting my mocked backend to return something that doesn't error on the .map(). The error I'm getting is:
this._http.get(...).map is not a function
I have been using this article as my main guide throughout.
If I remove the .map() from my service function, I don't get any errors. How can I get my mocked response to have a .map() function that I can call?
Note: I am currently using RC.4
Here is my service:
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import { AppSettings } from '../../../settings';
import { Brand } from '../../models/index';
#Injectable()
export class BrandDataService {
allBrands : Brand[];
groups : any;
groupNames : string[];
constructor (
private _http : Http
) {}
/**
* Get all brands
*/
public getAllBrands () :Observable<any> {
let url = AppSettings.BRAND_API_URL + 'brands';
return this._http.get( url )
.map( this.createAndCacheBrands )
.catch( (error) => {
return Observable.throw( error );
});
}
private createAndCacheBrands (res:Response) {
...
}
}
And here is my spec file, which is using MockBackend and other associated libraries to mock the backend for these tests:
// vendor dependencies
import { Http, BaseRequestOptions, Response, ResponseOptions, RequestMethod } from '#angular/http';
import { addProviders, inject } from '#angular/core/testing';
import { MockBackend, MockConnection } from '#angular/http/testing';
// Service to test
import { BrandDataService } from './brandData.service';
describe( 'Brand data service', () => {
let service : BrandDataService = null;
let backend : MockBackend = null;
// Provide a mock backend implementation
beforeEach(() => {
addProviders([
MockBackend,
BaseRequestOptions,
{
provide : Http,
useFactory : (backendInstance : MockBackend, defaultOptions : BaseRequestOptions) => {
return new Http(backendInstance, defaultOptions);
},
deps : [MockBackend, BaseRequestOptions]
},
BrandDataService
])
})
beforeEach (inject([BrandDataService, MockBackend], (_service : BrandDataService, mockBackend : MockBackend) => {
service = _service;
backend = mockBackend;
}));
it ('should return all brands as an Observable<Response> when asked', (done) => {
// Set the mock backend to respond with the following options:
backend.connections.subscribe((connection : MockConnection) => {
// Make some expectations on the request
expect(connection.request.method).toEqual(RequestMethod.Get);
// Decide what to return
let options = new ResponseOptions({
body : JSON.stringify({
success : true
})
});
connection.mockRespond(new Response(options));
});
// Run the test.
service
.getAllBrands()
.subscribe(
(data) => {
expect(data).toBeDefined();
done();
}
)
});
});
You need to import rxjs so you can use map:
import 'rxjs/Rx';
Or, you can import only map operator so your app doesn't load files you won't use:
import 'rxjs/add/operator/map';

Angular2, Ionic2 post to web service

import {Page, Platform} from 'ionic-angular';
import { Http, Headers, Response, RequestOptions, HTTP_PROVIDERS} from 'angular2/http';
import { bootstrap } from 'angular2/platform/browser';
import { Component, Injectable, Inject } from 'angular2/core';
import 'rxjs/Rx';
import { CORE_DIRECTIVES, FORM_DIRECTIVES } from 'angular2/common';
import {Observable} from 'rxjs/Observable';
#Page({
directives: [ CORE_DIRECTIVES, FORM_DIRECTIVES ],
templateUrl: 'build/pages/getting-started/getting-started.html'
})
#Injectable()
export class GettingStartedPage {
public platform;
public networkState;
private headers;
private _apiUrl = 'http://172.16.2.115:3004/message';
subject: string;
message: string;
comments: string;
constructor(platform: Platform, public http: Http) {
this.platform = platform;
this.headers = new Headers();
this.headers.append('Content-Type', 'application/x-www-form-urlencoded');
}
onSubmit(value) {
this.send(value.subject, value.body);
}
send(subject, body)
{
var message = "subject=" + subject + "&body=" + body;
let result = this.http.post(this._apiUrl,
body,
{
headers: this.headers
}).map(res => {
this.comments = res.json();
});
this.send(subject, body).subscribe(res => {
console.log(message);
console.log(this._apiUrl);
});
return result;
}
}
I am trying to create a mobile app using Ionic2 and Angular2 beta.This app will send an email using POST to a Rails web service. The Rails web service is working just fine. I dont seem to be getting to work the mobile app.
There was a misunderstanding
this.send(subject, body).subscribe(res => {
console.log(message);
console.log(this._apiUrl);
});
would be in a different method
onSubmit(value) {
this.send(value.subject, value.body)
.subscribe(res => {
console.log(message);
console.log(this._apiUrl);
});
}
send(subject, body)
{
var message = "subject=" + subject + "&body=" + body;
return this.http.post(this._apiUrl,
body,
{
headers: this.headers
}).map(res => {
this.comments = res.json();
});
}
You should refactor your code this way:
onSubmit(value) {
this.send(value.subject, value.body).subscribe(res => {
console.log(message);
console.log(this._apiUrl);
});
}
send(subject, body)
{
var message = "subject=" + subject + "&body=" + body;
let result = this.http.post(this._apiUrl,
body,
{
headers: this.headers
}).map(res => {
this.comments = res.json();
});
return result;
}