Merge pull request #32 from vige/amber-web-auth
Use Amber Web Authorization for login
This commit is contained in:
commit
052564963b
5 changed files with 31 additions and 202 deletions
|
@ -74,8 +74,6 @@ DISTFILES += qml/harbour-tooterb.qml \
|
||||||
qml/pages/LoginPage.qml \
|
qml/pages/LoginPage.qml \
|
||||||
qml/pages/Browser.qml \
|
qml/pages/Browser.qml \
|
||||||
qml/lib/API.js \
|
qml/lib/API.js \
|
||||||
qml/lib/server.py \
|
|
||||||
qml/lib/index.html \
|
|
||||||
qml/images/icon-s-following \
|
qml/images/icon-s-following \
|
||||||
qml/images/icon-s-bookmark \
|
qml/images/icon-s-bookmark \
|
||||||
qml/images/icon-m-bookmark \
|
qml/images/icon-m-bookmark \
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta name="viewport" content="width=device-width, user-scalable=no"/>
|
|
||||||
<style>
|
|
||||||
body { font-family: sans-serif; background-color:black;}
|
|
||||||
button { width: 32%; font-size: 20px; height: 40px; }
|
|
||||||
#output { width: 100%; text-align: center; font-size: 120px; }
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
function action(topic) {
|
|
||||||
var output = document.getElementById('output');
|
|
||||||
output.textContent = {"one": "1", "two": "2", "three": "3"}[topic]
|
|
||||||
}
|
|
||||||
function send(topic) {
|
|
||||||
var customEvent = new CustomEvent("framescript:log",
|
|
||||||
{detail: { topic: topic}});
|
|
||||||
document.dispatchEvent(customEvent);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="output"><p>Login Complete</p></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,43 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# POETASTER
|
|
||||||
import sys
|
|
||||||
sys.path.append('/usr/share/harbour-tooterb/qml')
|
|
||||||
sys.path.append('/usr/share/harbour-tooterb/qml/lib')
|
|
||||||
sys.path.append('/usr/share/harbour-tooterb/qml/pages')
|
|
||||||
|
|
||||||
# POETASTER
|
|
||||||
|
|
||||||
import pyotherside
|
|
||||||
import threading
|
|
||||||
import time
|
|
||||||
import random
|
|
||||||
import os
|
|
||||||
import http.server
|
|
||||||
import socketserver
|
|
||||||
|
|
||||||
PORT = 8000
|
|
||||||
directory = '/usr/share/harbour-tooterb/qml/lib'
|
|
||||||
Handler = http.server.SimpleHTTPRequestHandler
|
|
||||||
os.chdir(directory)
|
|
||||||
|
|
||||||
def serveMe():
|
|
||||||
with socketserver.TCPServer(("", PORT), Handler) as httpd:
|
|
||||||
print("serving at port", PORT)
|
|
||||||
pyotherside.send('finished', PORT)
|
|
||||||
httpd.serve_forever()
|
|
||||||
|
|
||||||
class Downloader:
|
|
||||||
def __init__(self):
|
|
||||||
# Set bgthread to a finished thread so we never
|
|
||||||
# have to check if it is None.
|
|
||||||
self.bgthread = threading.Thread()
|
|
||||||
self.bgthread.start()
|
|
||||||
|
|
||||||
def serve(self):
|
|
||||||
if self.bgthread.is_alive():
|
|
||||||
return
|
|
||||||
self.bgthread = threading.Thread(target=serveMe)
|
|
||||||
self.bgthread.start()
|
|
||||||
|
|
||||||
downloader = Downloader()
|
|
|
@ -1,34 +1,14 @@
|
||||||
import QtQuick 2.0
|
import QtQuick 2.0
|
||||||
import Sailfish.Silica 1.0
|
import Sailfish.Silica 1.0
|
||||||
import Sailfish.WebView 1.0
|
import Amber.Web.Authorization 1.0
|
||||||
import Sailfish.WebEngine 1.0
|
|
||||||
import io.thp.pyotherside 1.5
|
|
||||||
import "../lib/API.js" as Logic
|
import "../lib/API.js" as Logic
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Page {
|
Page {
|
||||||
property bool debug: false
|
property bool debug: false
|
||||||
|
|
||||||
// Python connections and signals, callable from QML side
|
|
||||||
// This is not ideal but keeps the page from erroring out on redirect
|
|
||||||
Python {
|
|
||||||
id: py
|
|
||||||
Component.onCompleted: {
|
|
||||||
addImportPath(Qt.resolvedUrl('../lib/'));
|
|
||||||
importModule('server', function () {});
|
|
||||||
|
|
||||||
setHandler('finished', function(newvalue) {
|
|
||||||
if(debug) console.debug(newvalue)
|
|
||||||
});
|
|
||||||
startDownload();
|
|
||||||
}
|
|
||||||
function startDownload() {
|
|
||||||
call('server.downloader.serve', function() {});
|
|
||||||
if (debug) console.debug("called")
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
id: loginPage
|
id: loginPage
|
||||||
// The effective value will be restricted by ApplicationWindow.allowedOrientations
|
// The effective value will be restricted by ApplicationWindow.allowedOrientations
|
||||||
allowedOrientations: Orientation.All
|
allowedOrientations: Orientation.All
|
||||||
|
@ -50,6 +30,28 @@ Page {
|
||||||
text: qsTr("Instance")
|
text: qsTr("Instance")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OAuth2Ac {
|
||||||
|
id: mastodonOAuth
|
||||||
|
authorizationEndpoint: instance.text + "/oauth/authorize"
|
||||||
|
tokenEndpoint: instance.text + "/oauth/token"
|
||||||
|
scopes: ["read", "write", "follow"]
|
||||||
|
redirectListener.port: 7538
|
||||||
|
|
||||||
|
onErrorOccurred: console.log("Mastodon OAuth2 Error: " + error.code + " = " + error.message + " : " + error.httpCode)
|
||||||
|
|
||||||
|
onReceivedAuthorizationCode: {
|
||||||
|
console.log("Got auth code, about to request token.")
|
||||||
|
}
|
||||||
|
|
||||||
|
onReceivedAccessToken: {
|
||||||
|
console.log("Got access token: " + token.access_token)
|
||||||
|
Logic.conf["api_user_token"] = token.access_token
|
||||||
|
Logic.conf["login"] = true;
|
||||||
|
Logic.api.setConfig("api_user_token", Logic.conf["api_user_token"])
|
||||||
|
pageStack.replace(Qt.resolvedUrl("MainPage.qml"), {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
id: instance
|
id: instance
|
||||||
focus: true
|
focus: true
|
||||||
|
@ -63,7 +65,7 @@ Page {
|
||||||
EnterKey.onClicked: {
|
EnterKey.onClicked: {
|
||||||
Logic.api = Logic.mastodonAPI({ instance: instance.text, api_user_token: "" });
|
Logic.api = Logic.mastodonAPI({ instance: instance.text, api_user_token: "" });
|
||||||
Logic.api.registerApplication("Tooter",
|
Logic.api.registerApplication("Tooter",
|
||||||
'http://localhost:8000/index.html', // redirect uri, we will need this later on
|
"http://127.0.0.1:7538",
|
||||||
["read", "write", "follow"], //scopes
|
["read", "write", "follow"], //scopes
|
||||||
"https://github.com/poetaster/harbour-tooter#readme", //website on the login screen
|
"https://github.com/poetaster/harbour-tooter#readme", //website on the login screen
|
||||||
function(data) {
|
function(data) {
|
||||||
|
@ -73,25 +75,15 @@ Page {
|
||||||
conf.instance = instance.text;
|
conf.instance = instance.text;
|
||||||
conf.login = false;
|
conf.login = false;
|
||||||
|
|
||||||
/*conf['login'] = false;
|
|
||||||
conf['mastodon_client_id'] = data['mastodon_client_id'];
|
|
||||||
conf['mastodon_client_secret'] = data['mastodon_client_secret'];
|
|
||||||
conf['mastodon_client_redirect_uri'] = data['mastodon_client_redirect_uri'];
|
|
||||||
delete Logic.conf;*/
|
|
||||||
Logic.conf = conf;
|
Logic.conf = conf;
|
||||||
if(debug) console.log(JSON.stringify(conf))
|
if(debug) console.log(JSON.stringify(conf))
|
||||||
if(debug) console.log(JSON.stringify(Logic.conf))
|
if(debug) console.log(JSON.stringify(Logic.conf))
|
||||||
// we got our application
|
// we got our application
|
||||||
|
|
||||||
// our user to it!
|
mastodonOAuth.clientId = conf["client_id"]
|
||||||
var url = Logic.api.generateAuthLink(Logic.conf["client_id"],
|
mastodonOAuth.clientSecret = conf["client_secret"];
|
||||||
Logic.conf["redirect_uri"],
|
|
||||||
"code", // oauth method
|
mastodonOAuth.authorizeInBrowser()
|
||||||
["read", "write", "follow"] //scopes
|
|
||||||
);
|
|
||||||
if(debug) console.log(url)
|
|
||||||
webView.url = url
|
|
||||||
webView.visible = true
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -114,96 +106,4 @@ Page {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WebView {
|
|
||||||
id: webView
|
|
||||||
|
|
||||||
/* This will probably be required from 4.4 on. */
|
|
||||||
Component.onCompleted: {
|
|
||||||
WebEngineSettings.setPreference("security.disable_cors_checks", true, WebEngineSettings.BoolPref)
|
|
||||||
WebEngineSettings.setPreference("security.fileuri.strict_origin_policy", false, WebEngineSettings.BoolPref)
|
|
||||||
}
|
|
||||||
onViewInitialized: {
|
|
||||||
//webview.loadFrameScript(Qt.resolvedUrl("../html/framescript.js"));
|
|
||||||
//webview.addMessageListener("webview:action");
|
|
||||||
//webview.runJavaScript("return latlon('" + lat + "','" + lon + "')");
|
|
||||||
}
|
|
||||||
|
|
||||||
onRecvAsyncMessage: {
|
|
||||||
if(debug) console.log('async changed: ' + url)
|
|
||||||
if(debug) console.debug(message)
|
|
||||||
switch (message) {
|
|
||||||
case "embed:contentOrientationChanged":
|
|
||||||
break
|
|
||||||
case "webview:action":
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
visible: false
|
|
||||||
//opacity: 0
|
|
||||||
anchors.fill: parent
|
|
||||||
/*{
|
|
||||||
top: parent.top
|
|
||||||
left: parent.left
|
|
||||||
right: parent.right
|
|
||||||
bottom: parent.bottom
|
|
||||||
}*/
|
|
||||||
|
|
||||||
onLoadingChanged: {
|
|
||||||
if(debug) console.log('loading changed: ' + url)
|
|
||||||
if (
|
|
||||||
(url+"").substr(0, 38) === 'http://localhost:8000/index.html?code=' ||
|
|
||||||
(url+"").substr(0, 39) === 'https://localhost:8000/index.html?code='
|
|
||||||
) {
|
|
||||||
visible = false;
|
|
||||||
|
|
||||||
var vars = {};
|
|
||||||
(url+"").replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) { vars[key] = value;}); /* found on https://html-online.com/articles/get-url-parameters-javascript/ */
|
|
||||||
|
|
||||||
var authCode = vars["code"];
|
|
||||||
|
|
||||||
if(debug) console.log(authCode)
|
|
||||||
|
|
||||||
Logic.api.getAccessTokenFromAuthCode(
|
|
||||||
Logic.conf["client_id"],
|
|
||||||
Logic.conf["client_secret"],
|
|
||||||
Logic.conf["redirect_uri"],
|
|
||||||
authCode,
|
|
||||||
function(data) {
|
|
||||||
// AAAND DATA CONTAINS OUR TOKEN!
|
|
||||||
if(debug) console.log(data)
|
|
||||||
data = JSON.parse(data)
|
|
||||||
if(debug) console.log(JSON.stringify(data))
|
|
||||||
if(debug) console.log(JSON.stringify(data.access_token))
|
|
||||||
Logic.conf["api_user_token"] = data.access_token
|
|
||||||
Logic.conf["login"] = true;
|
|
||||||
Logic.api.setConfig("api_user_token", Logic.conf["api_user_token"])
|
|
||||||
pageStack.replace(Qt.resolvedUrl("MainPage.qml"), {})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*switch (loadRequest.status)
|
|
||||||
{
|
|
||||||
case WebView.LoadSucceededStatus:
|
|
||||||
opacity = 1
|
|
||||||
break
|
|
||||||
case WebView.LoadFailedStatus:
|
|
||||||
//opacity = 0
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
//opacity = 0
|
|
||||||
break
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
FadeAnimation on opacity {}
|
|
||||||
|
|
||||||
PullDownMenu {
|
|
||||||
MenuItem {
|
|
||||||
text: qsTr("Reload")
|
|
||||||
onClicked: webView.reload()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ Source0: %{name}-%{version}.tar.bz2
|
||||||
Requires: sailfishsilica-qt5 >= 0.10.9
|
Requires: sailfishsilica-qt5 >= 0.10.9
|
||||||
Requires: nemo-qml-plugin-configuration-qt5
|
Requires: nemo-qml-plugin-configuration-qt5
|
||||||
Requires: nemo-qml-plugin-notifications-qt5
|
Requires: nemo-qml-plugin-notifications-qt5
|
||||||
Requires: pyotherside-qml-plugin-python3-qt5
|
Requires: amber-web-authorization
|
||||||
|
|
||||||
BuildRequires: qt5-qttools-linguist
|
BuildRequires: qt5-qttools-linguist
|
||||||
BuildRequires: pkgconfig(sailfishapp) >= 1.0.2
|
BuildRequires: pkgconfig(sailfishapp) >= 1.0.2
|
||||||
|
|
Loading…
Reference in a new issue