I'm writing an Ubuntu Touch application in QML. I'd like to integrate with Trello. There are two ways to log into Trello in the API, one of which is OAuth, which I plan on using. What is the best way to do this from QML? I'd prefer not to use a C++ backend, but I am willing to do so if that is the only way.
-
So I know your app now integrates with Trello. Care to answer your own question? – andrewsomething Mar 02 '14 at 16:08
-
@andrewsomething There are two ways, one is to use OAuth and the other involves opening an external URL and having the user copy back a token. I'm using the second option, without using OAuth. If you'd find a detailed explanation useful even though I'm not using OAuth, I can do a full answer. – iBelieve Mar 02 '14 at 18:59
2 Answers
You could create an account plugin for Trello, so that a Trello account could be created from the "Online Account" panel in the System Settings. The you could use the Ubuntu.OnlineAccounts QML module to login, like this:
import QtQuick 2.0
import Ubuntu.OnlineAccounts 0.1
Rectangle {
width: 400
height: 300
AccountServiceModel {
id: accounts
service: "trello-board"
}
ListView {
id: listView
anchors.fill: parent
model: accounts
delegate: Item {
width: parent.width
height: 60
AccountService {
id: accts
objectHandle: accountServiceHandle
onAuthenticated: { console.log("Access token is " + reply.AccessToken) }
onAuthenticationError: { console.log("Authentication failed, code " + error.code) }
}
Text {
anchors.fill: parent
text: providerName + ": " + displayName
MouseArea {
anchors.fill: parent
onClicked: accts.authenticate(null)
}
}
}
}
}
This code will get you the OAuth token. In order to create the account in the first place, you need to create the following files:
/usr/share/accounts/providers/trello.provider/usr/share/accounts/services/trello-board.service/usr/share/accounts/qml-plugins/trello/Main.qml
Given that Trello uses OAuth 1.0 like Flickr and twitter, just create the above files using the twitter or flickr version as a template, and modify them as needed (for the .service file, you could use flickr-sharing.service); in trello.provider you'll need to change the API endpoints as following:
<setting name="RequestEndpoint">https://trello.com/1/OAuthGetRequestToken</setting>
<setting name="TokenEndpoint">https://trello.com/1/OAuthGetAccessToken</setting>
<setting name="AuthorizationEndpoint">https://trello.com/1/OAuthAuthorizeToken</setting>
And of course, change the other fields (callback URL, client ID and secret) to match those you set when you registered your app with Trello. If all goes well, you'll be able to create a Trello account from the "Online Accounts" panel in the System Settings.
- 498
- 2
- 7
-
I followed your method, and it showed up in Online Accounts, but when I try to add my Trello account, I'm told that "Your browser is not supported" – iBelieve Aug 26 '13 at 16:03
-
1This is a great start, but it doesn't really explain then how to use it. Especially for an api that requires signed requests – Chris Wayne Sep 01 '13 at 02:54
Since the approach that mardy uses isn't actually available to apps under confinement on Ubuntu Touch, it is necessary to do the OAuth dance your self. Essentially, you need to load the login page in a WebView and then intercept the response using the onUrlChanged signal to extract the auth token. Below is an example using StackExchange's own OAuth implementation.
In OAuth.qml:
import QtQuick 2.0
import QtWebKit 3.0
import "OAuth.js" as OAuth
Rectangle {
height: 750
width: 500
Text {
id: nextState
visible: false
anchors.centerIn: parent
text: "Log in successful!"
}
Item {
id: stackOAuth
property string nextState: "AuthDone"
anchors.fill: parent
Component.onCompleted: OAuth.checkToken()
property string token: ""
WebView {
id: loginView
visible: false
anchors.fill: parent
onUrlChanged: OAuth.urlChanged(url)
}
Rectangle {
height: 50
width: parent.width
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
Text {
text: loginView.url
}
}
states: [
State {
name: "Login"
PropertyChanges {
target: loginView
visible: true
url: "https://stackexchange.com/oauth/dialog"+
"?redirect_uri=https://stackexchange.com/oauth/login_success"+
"&client_id=YOUR_CLIENT_ID&scope=read_inbox"
}
},
State {
name: "AuthDone"
PropertyChanges {
target: loginView
visible: false
opacity: 0
}
PropertyChanges {
target: nextState
visible: true
}
}
]
}
}
Then in OAuth.js you have code to extract the token from the url and handel storing/checking it from your database:
.import QtQuick.LocalStorage 2.0 as Sql
function urlChanged(url) {
var authorized = false;
var mUrl = url.toString();
var token = "";
if (mUrl.indexOf("https://stackexchange.com") > -1) {
var query = mUrl.substring(mUrl.indexOf('#') + 1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if (pair[0] == "access_token") {
authorized = true;
token = pair[1];
console.log("Found token: " + token)
saveToken(token);
}
}
}
if (authorized) {
stackOAuth.token = token;
stackOAuth.state = "AuthDone";
}
}
function saveToken(token) {
console.log("Saving...")
var db = Sql.LocalStorage.openDatabaseSync("Token", "1.0", "the token", 1);
var dataStr = "INSERT INTO Token VALUES(?)";
var data = [token];
db.transaction(function(tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS Token(token TEXT)');
tx.executeSql(dataStr, data);
});
}
function checkToken() {
var db = Sql.LocalStorage.openDatabaseSync("Token", "1.0", "the token", 1);
var dataStr = "SELECT * FROM Token";
db.transaction(function(tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS Token(token TEXT)');
var rs = tx.executeSql(dataStr);
if (rs.rows.item(0)) {
stackOAuth.token = rs.rows.item(0).token
stackOAuth.state = "AuthDone"
console.log("Auth done...")
} else {
stackOAuth.state = "Login"
console.log("Logging in....")
}
});
}
This example is (more or less) a port of the old QtQuick 1.0 example from Nokia to QtQuick 2.0.
- 37,262
- 13
- 93
- 140
-
Wonder why the down vote? If there's an issue, I'd be happy to update the answer. It definitely worked when I wrote it nearly a year ago... – andrewsomething Mar 16 '15 at 22:01
-
The assertion that adding account providers in the confined phone world isn't possible, is no longer valid. It is possible for click packages to provide account plug-ins for OAuth based services, for a while now. – dobey Jun 03 '16 at 01:41