quickblox web how to upload profile picture - quickblox

I'm trying to upload a profile picture (blob_id) from a javascript document and I can't find a way, I donĀ“t know if I should use this snippets or even how to use it :(
I'll be so thankfull if you could help me
Thanks
QB.users.update({ id: user_creds.user_id, website: "http://quickblox.com"}, function(error, response){
if(error) {
console.log(error);
} else {
// Success
}
});

sorry about this. We'll be beefing up the documentation soon.
Here's how to upload a profile picture
We'll have a file input:
<input type="file" id="picture" />
Then assuming you have jQuery in your environment, we'll reference it like this:
var profile_picture = $("#picture")[0].files;
Then you upload the file to Quickblox AWS like so:
QB.content.createAndUpload({file: profile_picture, public: true}, function(error, response) {
if (error) {
console.log("upload didn't work");
} else {
var blob_id = response.id;
}
});
As you can see, the ID of the blob is the id field of the response.
You then add this blob ID as the blob_id field of a new user when you create him/her:
QB.users.create({login: "username_here", password: "password_here", blob_id: blob_id_here}, function(error, response){
if(error) {
console.log(error);
} else {
}
});
I made a page which demos the uploading functionality of the Javascript SDK - you can check it out here: http://www.quickblox.com/alex/websdk/upload.html

Related

Web app that runs in Microsoft Teams (personal tab) doesn't always work on Desktop version

I have a Web app built in Vuejs and has SSO authentification using microsoftTeams.authentication.getAuthToken when running in Teams, or microsoftAuthLib when running in the browser.
Inside the company's network or when connected to the VPN everything works absolutely fine.
We recently opened it outside of the VPN and we created a public certificate for it. So when I disconnect the VPN, it works:
In any browser (outside of Teams).
Teams browser version.
Teams on Android/iPhone.
But it doesn't work on Teams Windows Desktop version, it fails with the following error:
Refused to display
'https://login.microsoftonline.com/.../oauth2/authorize?...' in a
frame because it set 'X-Frame-Options' to 'deny'.
Anybody has an idea what could be the issue? And why would it work on the company's VPN but not outside?And only on specific cases? I am lost, any help would be appreciated.
Thank you
*** EDIT / ADDED SSO REDIRECT CODE ***
import * as microsoftTeams from "#microsoft/teams-js";
import * as microsoftAuthLib from "msal";
import settings from './settings.js';
var msalConfig = {
auth: {
clientId: settings.sso.id,
authority: settings.sso.authority
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: true
}
};
var requestObj = {
scopes: settings.sso.scopes
};
var myMSALObj = new microsoftAuthLib.UserAgentApplication(msalConfig);
myMSALObj.handleRedirectCallback(authRedirectCallBack);
function authRedirectCallBack(error, response) {
if (error) {
console.log(error);
} else {
console.log("token type is:" + response.tokenType);
}
}
function loginRedirect(requestObj) {
let account = myMSALObj.getAccount();
if (!account) {
myMSALObj.loginRedirect(requestObj);
return false;
} else {
return true;
}
}
function acquireMsalToken() {
return new Promise(function (resolve) {
resolve(myMSALObj.acquireTokenSilent(requestObj).then(token => {
return token.accessToken;
}).catch(error => {
acquireMsalTokenRedirect(error);
}));
})
}
function acquireTeamsToken() {
return new Promise((resolve, reject) => {
microsoftTeams.authentication.getAuthToken({
successCallback: (result) => {
resolve(result);
},
failureCallback: (error) => {
reject(error);
}
});
});
}
function acquireMsalTokenRedirect(error) {
if (error.errorCode === "consent_required" ||
error.errorCode === "interaction_required" ||
error.errorCode === "login_required") {
myMSALObj.acquireTokenRedirect(requestObj);
}
}
var msal = {
autoSignIn: function () {
return loginRedirect(requestObj);
},
acquireToken: async function () {
if (settings.sso.inTeams) {
microsoftTeams.initialize();
microsoftTeams.enterFullscreen();
return acquireTeamsToken();
} else {
let signedIn = msal.autoSignIn();
if (signedIn) {
return acquireMsalToken();
}
}
}
}
export default msal
This error means that you are trying to redirect your tab's iframe to the AAD login flow which in turn is unable to silently generate an auth token for you and is attempting to show an interactive flow (e.g. sign in or consent):
Refused to display
'https://login.microsoftonline.com/.../oauth2/authorize?...' in a
frame because it set 'X-Frame-Options' to 'deny'.
To avoid this issue you need to try and acquire a token silently and if that fails use the microsoftTeams.authentication.authenticate API to open a popup window and conduct the AAD login flow there.
Replacing the acquireTeamsToken() function with the following resolved the issue.
function acquireTeamsToken() {
return new Promise((resolve, reject) => {
microsoftTeams.initialize(() => {
microsoftTeams.authentication.authenticate({
url: window.location.origin + "/ms-teams/auth-start",
width: 600,
height: 535,
successCallback: (result) => {
resolve(result);
},
failureCallback: (error) => {
reject(error);
}
});
});
});
}
I found this documentation very helpful on how to create the Authentication pop up and how to create a Callback window with the Token in it.
You might also want to cache the token and only create a popup when it expires.
This might be because you're using the auth popup option instead of the redirect option in whichever auth library you're using (hopefully MSAL 2.0). Teams is a little different because it's actually launching a popup for you when necessary, so although it sounds a bit strange, you actually want to use the redirect option, inside the popup that is launched. What might help is to look at the new SSO Sample app in the Teams PnP samples.
Go to: %APPDATA%\Microsoft\Teams
Open the file hooks.json (if it's not there, create it)
Add the following to it: {"enableSso": false, "enableSsoMac": false}
That's it, now Teams desktop has the same authentication workflow as the browser version. Have a nice day.

SPFx Graph API Response Handling

My SPFx webpart is working well until I try to return the result of an Graph API call. The below code is trying to get the users that have permissions to the root file library for the site the webpart is installed.
The console.log("Reached the Graph") shows up in the inspector console so I'm guessing it has something to do with the .push() I'm using to append each returned record to the response declared at the beginning of the method.
I also tried the more documented .forEach() below without success. Any Ideas?
private _loadUser(): MicrosoftGraph.Permission[] {
let response: MicrosoftGraph.Permission[];
this.props.context.msGraphClientFactory
.getClient()
.then((client: MSGraphClient): void => {
let apiUrl: string = '/groups/'+this.props.group+'/drive/items/root/permissions';
client
.api(apiUrl)
.version("v1.0")
.get((error?, result?: MicrosoftGraph.Permission[], rawResponse?: any) => {
// handle the response
if(error){
console.error(error);
}
if (result) {
console.log("Reached the Graph");
for (let res of result){
response.push(res);
}
}
}
);
});
return response;
}
result.forEach(element => {
response.push(element);
console.log(element.grantedTo.user.displayName);
});

Cloud Storage getDownloadURL()

I am trying to retrieve downloadable URL of images in my Firestore database. This is my code:
var storageRef = firebase.storage().ref();
storageRef
.child(`tutorials/images/${filename}`)
.getDownloadURL()
.then(function(url) {
this.setState({ imgURL: url });
console.log(url);
})
.catch(function(error) {
console.warn(error);
});
but I get a error RNFIrebaseStoragepromiseRejectStorageException error. Anyone have a solution to how I can successfully retrieve the downloadable URL from the Firestore? Thanks.
Things to try:
Try to download a hardcoded URL, just to be sure the path exists
Double check your storage permissions.

Upload images from React Native to LoopBack

I need to upload a selection of images that user picked from CameraRoll to the LoopBack Component Storage. The thing is that the component storage is working fine, because I can upload and download the files through Postman. But, when I try to upload from react native to loopback, it always returns "No file content upload" with http status 400.
I read a lot of people talking about it and tried everything and none worked for me.
First, I am taking the images from the CameraRoll and my images array looks like this:
[
{
exists: 1,
file: "assets-library://asset/asset.JPG?id=3FF3C864-3A1A-4E55-9455-B56896DDBF1F&ext=JPG",
isDirectory: 0,
md5: "428c2e462a606131428ed4b45c695030",
modificationTime: 1535592967.3309255,
size: 153652,
uri: null
}
]
In the example above I just selected one image.
I transformed to Blob, then I got:
[
{
_data: {
blobId: "3FF3C864-3A1A-4E55-9455-B56896DDBF1F",
name: "asset.JPG",
offset: 0,
size: 153652,
type: "image/jpeg"
}
}
]
So I tried a lot of things after this, tried to send the blob itself as the request body, tried to append to a form data and send the form data, but it doesn't matter the way I try, I always get the "No file content upload" response.
I also tried the example from Facebook, didn't work: https://github.com/facebook/react-native/blob/master/Libraries/Network/FormData.js#L28
The way I am trying now:
In my view:
finalizarCadastro = async () => {
let formData = new FormData();
let blobs = [];
for(let i=0;i<this.state.fotos.length;i++){
let response = await fetch(this.state.fotos[i]);
let blob = await response.blob();
blobs.push(blob);
}
formData.append("files", blobs);
this.props.servico.criar(formData);
}
And the function that send to my server:
criar: (servico) => {
this.setState({carregando: true});
axios.post(`${REQUEST_URL}/arquivos/seila/upload`, servico, {headers: {'content-type': 'multipart/form-data'}}).then(() => {
this.setState({carregando: false});
this.props.alertWithType("success", "Sucesso", "Arquivo salvo com sucesso");
}).catch(error => {
this.setState({carregando: false});
console.log(error.response);
this.props.alertWithType("error", "Erro", error.response.data.error.message);
})
}
I found the solution. So the problem was actually not the code itself, the problem was sending multiple files at the same time. To fix everything, I did this:
this.state.fotos.forEach((foto, i) => {
formData.append(`foto${i}`, {
uri: foto,
type: "image/jpg",
name: "foto.jpg"
});
})
this.props.servico.criar(formData);
And my function that sends the request to the server:
criar: (servico) => {
this.setState({carregando: true});
axios.post(`${REQUEST_URL}/arquivos/seila/upload`, servico).then((response) => {
this.setState({carregando: false});
this.props.alertWithType("success", "Sucesso", "Arquivo salvo com sucesso");
}).catch(error => {
this.setState({carregando: false});
this.props.alertWithType("error", "Erro", error.response.data.error.message);
})
},
So you don't need to set the Content-Type header to multipart/form-data and don't need to transform the images to blob, actually you just need the uri of each one, and I think the type and name attributes are opcional.

quickblox - how can I get content by owner?

I'm working on a CMS and I'd like to know if I can get the content by owner, in other to show the pictures from the app's users.
I know that i can get the content list of the current user with:
QB.content.list(function(error, response){
if(error) {
console.log(error);
} else {
// Success
}
});
but can I access to other user's content?
thank you very much
Unfortunately, this functionality isn't in the API right now. If it's profile pictures you want, you can just use the blob parameter on a user.
If you can provide us some good use cases for - send me an email at alex.bass#quickblox.com and we'll consider adding it.
Hopefully this hasn't inconvenienced you too much.
EDIT:
I've just been informed by my colleague that there is a way around this - it's not perfect, but it does get the job done.
You can create a custom objects class with just 2 fields: blob_id and user_id. Then when content is uploaded, just add a record in the callback.
Here's the complete code - I haven't tested it though. Let me know if you have any troubles.
When uploading:
QB.init(app_id, auth_key, auth_secret);
var user_id;
QB.createSession({login: <username>, password: <password>}, function(error, response){
if(error) {
console.log(error);
} else {
// Just making a record of the user_id for use later
user_id = response.id;
}
});
//
// later...
//
var files = $("input[type=file]")[0].files;
// This function will create "content" record in QB, then when QB returns AWS URL to
// post to, it will automatically upload it, then on completion, mark uploaded.
QB.content.createAndUpload({'file': files, 'public': true}, function(err, response){
if (err) {
console.log(err);
} else {
// Response will contain blob ID.
var data = {
blob_id: response.id,
blob_owner: user_id
}
QB.data.create("BlobsToUsers", data, function(err, response){
if (err) {
console.log(err);
} else {
// Done
}
});
}
});
Then, later on when you're listing content:
QB.data.list("BlobsToUsers", { blob_owner: user_id } function(err, response){
if (err) {
console.log(err);
} else {
// response.items will be array of all records with the specified blob_owner.
// You could also filter by date, timestamp or whatever you want.
}
});
To break it down into steps:
Use "QB.content.createAndUpload()" to upload data
Create custom objects record matching blob ID to owner
Later, when listing, get records from Custom Objects.
Do whatever you want from there. There is a function named "QB.content.getFileUrl()" that will return an AWS URL that you use for an <img> tag.
Hope this helps