This commit is contained in:
Nolan Lawson 2018-01-27 13:38:57 -08:00
parent 537071d00e
commit 94e06ca7f8
2 changed files with 112 additions and 99 deletions

View File

@ -0,0 +1,105 @@
import { getAccessTokenFromAuthCode, registerApplication, generateAuthLink } from '../../../_utils/mastodon/oauth'
import { getVerifyCredentials } from '../../../_utils/mastodon/user'
import { getInstanceInfo } from '../../../_utils/mastodon/instance'
import { goto } from 'sapper/runtime.js'
import { switchToTheme } from '../../../_utils/themeEngine'
import { database } from '../../../_utils/database/database'
import { store } from '../../../_utils/store'
const REDIRECT_URI = (typeof location !== 'undefined' ?
location.origin : 'https://pinafore.social') + '/settings/instances/add'
store.onchange((state, changed) => {
if (changed['instanceNameInSearch']) {
store.set({logInToInstanceError: false})
}
})
async function redirectToOauth() {
let instanceName = store.get('instanceNameInSearch')
let loggedInInstances = store.get('loggedInInstances')
instanceName = instanceName.replace(/^https?:\/\//, '').replace('/$', '')
if (Object.keys(loggedInInstances).includes(instanceName)) {
store.set({logInToInstanceError: `You've already logged in to ${instanceName}`})
return
}
let registrationPromise = registerApplication(instanceName, REDIRECT_URI)
let instanceInfo = await getInstanceInfo(instanceName)
await database.setInstanceInfo(instanceName, instanceInfo) // cache for later
let instanceData = await registrationPromise
store.set({
currentRegisteredInstanceName: instanceName,
currentRegisteredInstance: instanceData
})
store.save()
let oauthUrl = generateAuthLink(
instanceName,
instanceData.client_id,
REDIRECT_URI
)
document.location.href = oauthUrl
}
export async function logInToInstance() {
store.set({logInToInstanceLoading: true})
try {
await redirectToOauth()
} catch (err) {
console.error(err)
let error = `${err.message || err.name}. ` +
(navigator.onLine ?
`Is this a valid Mastodon instance?` :
`Are you offline?`)
store.set({logInToInstanceError: error})
} finally {
store.set({logInToInstanceLoading: false})
}
}
async function registerNewInstance(code) {
let currentRegisteredInstanceName = store.get('currentRegisteredInstanceName')
let currentRegisteredInstance = store.get('currentRegisteredInstance')
let instanceData = await getAccessTokenFromAuthCode(
currentRegisteredInstanceName,
currentRegisteredInstance.client_id,
currentRegisteredInstance.client_secret,
code,
REDIRECT_URI
)
let loggedInInstances = store.get('loggedInInstances')
let loggedInInstancesInOrder = store.get('loggedInInstancesInOrder')
let instanceThemes = store.get('instanceThemes')
instanceThemes[currentRegisteredInstanceName] = 'default'
loggedInInstances[currentRegisteredInstanceName] = instanceData
if (!loggedInInstancesInOrder.includes(currentRegisteredInstanceName)) {
loggedInInstancesInOrder.push(currentRegisteredInstanceName)
}
store.set({
instanceNameInSearch: '',
currentRegisteredInstanceName: null,
currentRegisteredInstance: null,
loggedInInstances: loggedInInstances,
currentInstance: currentRegisteredInstanceName,
loggedInInstancesInOrder: loggedInInstancesInOrder,
instanceThemes: instanceThemes
})
store.save()
switchToTheme('default')
// fire off request for account so it's cached
getVerifyCredentials(currentRegisteredInstanceName, instanceData.access_token).then(verifyCredentials => {
database.setInstanceVerifyCredentials(currentRegisteredInstanceName, verifyCredentials)
})
goto('/')
}
export async function handleOauthCode(code) {
try {
store.set({logInToInstanceLoading: true})
await registerNewInstance(code)
} catch (err) {
store.set({logInToInstanceError: `${err.message || err.name}. Failed to connect to instance.`})
} finally {
store.set({logInToInstanceLoading: false})
}
}

View File

@ -6,7 +6,7 @@
<SettingsLayout page='settings/instances/add' label="Add an Instance"> <SettingsLayout page='settings/instances/add' label="Add an Instance">
<h1 id="add-an-instance-h1">Add an Instance</h1> <h1 id="add-an-instance-h1">Add an Instance</h1>
<LoadingMask show="{{loading}}"/> <LoadingMask show="{{$logInToInstanceLoading}}"/>
{{#if $isUserLoggedIn}} {{#if $isUserLoggedIn}}
<p>Connect to an instance to log in.</p> <p>Connect to an instance to log in.</p>
@ -16,9 +16,9 @@
<form class="add-new-instance" on:submit='onSubmit(event)' aria-labelledby="add-an-instance-h1"> <form class="add-new-instance" on:submit='onSubmit(event)' aria-labelledby="add-an-instance-h1">
{{#if error}} {{#if $logInToInstanceError}}
<div class="form-error" role="alert"> <div class="form-error" role="alert">
Error: {{error}} Error: {{$logInToInstanceError}}
</div> </div>
{{/if}} {{/if}}
@ -70,27 +70,16 @@
<script> <script>
import Layout from '../../_components/Layout.html'; import Layout from '../../_components/Layout.html';
import SettingsLayout from '../_components/SettingsLayout.html' import SettingsLayout from '../_components/SettingsLayout.html'
import { registerApplication, generateAuthLink, getAccessTokenFromAuthCode } from '../../_utils/mastodon/oauth'
import { getVerifyCredentials } from '../../_utils/mastodon/user'
import { getInstanceInfo } from '../../_utils/mastodon/instance'
import { store } from '../../_utils/store' import { store } from '../../_utils/store'
import { goto } from 'sapper/runtime.js'
import { switchToTheme } from '../../_utils/themeEngine'
import LoadingMask from '../../_components/LoadingMask' import LoadingMask from '../../_components/LoadingMask'
import { database } from '../../_utils/database/database' import { logInToInstance, handleOauthCode } from './_actions/add'
const REDIRECT_URI = (typeof location !== 'undefined' ?
location.origin : 'https://pinafore.social') + '/settings/instances/add'
export default { export default {
async oncreate () { async oncreate () {
let params = new URLSearchParams(location.search) let params = new URLSearchParams(location.search)
if (params.has('code')) { if (params.has('code')) {
this.onReceivedOauthCode(params.get('code')) handleOauthCode(params.get('code'))
} }
this.store.observe('instanceNameInSearch', () => {
this.set({error: false})
})
}, },
components: { components: {
Layout, Layout,
@ -99,90 +88,9 @@
}, },
store: () => store, store: () => store,
methods: { methods: {
onSubmit: async function(event) { onSubmit(event) {
event.preventDefault() event.preventDefault()
this.set({loading: true}) logInToInstance()
try {
await this.redirectToOauth()
} catch (err) {
console.error(err)
let error = `${err.message || err.name}. ` +
(navigator.onLine ?
`Is this a valid Mastodon instance?` :
`Are you offline?`)
this.set({error: error})
} finally {
this.set({loading: false})
}
},
redirectToOauth: async function() {
let instanceName = this.store.get('instanceNameInSearch')
let loggedInInstances = this.store.get('loggedInInstances')
instanceName = instanceName.replace(/^https?:\/\//, '').replace('/$', '')
if (Object.keys(loggedInInstances).includes(instanceName)) {
this.set({error: `You've already logged in to ${instanceName}`})
return
}
let registrationPromise = registerApplication(instanceName, REDIRECT_URI)
let instanceInfo = await getInstanceInfo(instanceName)
await database.setInstanceInfo(instanceName, instanceInfo) // cache for later
let instanceData = await registrationPromise
this.store.set({
currentRegisteredInstanceName: instanceName,
currentRegisteredInstance: instanceData
})
this.store.save()
let oauthUrl = generateAuthLink(
instanceName,
instanceData.client_id,
REDIRECT_URI
)
document.location.href = oauthUrl
},
onReceivedOauthCode: async function(code) {
try {
this.set({loading: true})
await this.registerNewInstance(code)
} catch (err) {
this.set({error: `${err.message || err.name}. Failed to connect to instance.`})
} finally {
this.set({loading: false})
}
},
registerNewInstance: async function (code) {
let currentRegisteredInstanceName = this.store.get('currentRegisteredInstanceName')
let currentRegisteredInstance = this.store.get('currentRegisteredInstance')
let instanceData = await getAccessTokenFromAuthCode(
currentRegisteredInstanceName,
currentRegisteredInstance.client_id,
currentRegisteredInstance.client_secret,
code,
REDIRECT_URI
)
let loggedInInstances = this.store.get('loggedInInstances')
let loggedInInstancesInOrder = this.store.get('loggedInInstancesInOrder')
let instanceThemes = this.store.get('instanceThemes')
instanceThemes[currentRegisteredInstanceName] = 'default'
loggedInInstances[currentRegisteredInstanceName] = instanceData
if (!loggedInInstancesInOrder.includes(currentRegisteredInstanceName)) {
loggedInInstancesInOrder.push(currentRegisteredInstanceName)
}
this.store.set({
instanceNameInSearch: '',
currentRegisteredInstanceName: null,
currentRegisteredInstance: null,
loggedInInstances: loggedInInstances,
currentInstance: currentRegisteredInstanceName,
loggedInInstancesInOrder: loggedInInstancesInOrder,
instanceThemes: instanceThemes
})
this.store.save()
switchToTheme('default')
// fire off request for account so it's cached
getVerifyCredentials(currentRegisteredInstanceName, instanceData.access_token).then(verifyCredentials => {
database.setInstanceVerifyCredentials(currentRegisteredInstanceName, verifyCredentials)
})
goto('/')
} }
} }
} }