Some checks failed
Open PR on Staging / audit_and_check (pull_request) Failing after 9s
139 lines
3.6 KiB
TypeScript
139 lines
3.6 KiB
TypeScript
import { EventTemplate } from 'nostr-tools'
|
|
import { MetadataController, NostrController } from '.'
|
|
import {
|
|
setAuthState,
|
|
setMetadataEvent,
|
|
setRelayMapAction
|
|
} from '../store/actions'
|
|
import store from '../store/store'
|
|
import {
|
|
base64DecodeAuthToken,
|
|
base64EncodeSignedEvent,
|
|
getAuthToken,
|
|
getVisitedLink,
|
|
saveAuthToken,
|
|
compareObjects,
|
|
unixNow
|
|
} from '../utils'
|
|
import { appPrivateRoutes } from '../routes'
|
|
import { SignedEvent } from '../types'
|
|
|
|
export class AuthController {
|
|
private nostrController: NostrController
|
|
private metadataController: MetadataController
|
|
|
|
constructor() {
|
|
this.nostrController = NostrController.getInstance()
|
|
this.metadataController = new MetadataController()
|
|
}
|
|
|
|
/**
|
|
* Function will authenticate user by signing an auth event
|
|
* which is done by calling the sign() function, where appropriate
|
|
* method will be chosen (extension, nsecbunker or keys)
|
|
*
|
|
* @param pubkey of the user trying to login
|
|
* @returns url to redirect if authentication successfull
|
|
* or error if otherwise
|
|
*/
|
|
async authAndGetMetadataAndRelaysMap(pubkey: string) {
|
|
const emptyMetadata = this.metadataController.getEmptyMetadataEvent()
|
|
|
|
this.metadataController
|
|
.findMetadata(pubkey)
|
|
.then((event) => {
|
|
if (event) {
|
|
store.dispatch(setMetadataEvent(event))
|
|
} else {
|
|
store.dispatch(setMetadataEvent(emptyMetadata))
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
console.warn('Error occurred while finding metadata', err)
|
|
|
|
store.dispatch(setMetadataEvent(emptyMetadata))
|
|
})
|
|
|
|
// Nostr uses unix timestamps
|
|
const timestamp = unixNow()
|
|
const { hostname } = window.location
|
|
|
|
const authEvent: EventTemplate = {
|
|
kind: 27235,
|
|
tags: [],
|
|
content: `${hostname}-${timestamp}`,
|
|
created_at: timestamp
|
|
}
|
|
|
|
const signedAuthEvent = await this.nostrController.signEvent(authEvent)
|
|
this.createAndSaveAuthToken(signedAuthEvent)
|
|
|
|
store.dispatch(
|
|
setAuthState({
|
|
loggedIn: true,
|
|
usersPubkey: pubkey
|
|
})
|
|
)
|
|
|
|
const relayMap = await this.nostrController.getRelayMap(pubkey)
|
|
|
|
if (Object.keys(relayMap).length < 1) {
|
|
// Navigate user to relays page if relay map is empty
|
|
return Promise.resolve(appPrivateRoutes.relays)
|
|
}
|
|
|
|
if (store.getState().auth?.loggedIn) {
|
|
if (!compareObjects(store.getState().relays?.map, relayMap.map))
|
|
store.dispatch(setRelayMapAction(relayMap.map))
|
|
}
|
|
|
|
const currentLocation = window.location.hash.replace('#', '')
|
|
|
|
if (!Object.values(appPrivateRoutes).includes(currentLocation)) {
|
|
// User did change the location to one of the private routes
|
|
const visitedLink = getVisitedLink()
|
|
|
|
if (visitedLink) {
|
|
const { pathname, search } = visitedLink
|
|
|
|
return Promise.resolve(`${pathname}${search}`)
|
|
} else {
|
|
// Navigate user in
|
|
return Promise.resolve(appPrivateRoutes.homePage)
|
|
}
|
|
}
|
|
}
|
|
|
|
checkSession() {
|
|
const savedAuthToken = getAuthToken()
|
|
|
|
if (savedAuthToken) {
|
|
const signedEvent = base64DecodeAuthToken(savedAuthToken)
|
|
|
|
store.dispatch(
|
|
setAuthState({
|
|
loggedIn: true,
|
|
usersPubkey: signedEvent.pubkey
|
|
})
|
|
)
|
|
|
|
return
|
|
}
|
|
|
|
store.dispatch(
|
|
setAuthState({
|
|
loggedIn: false,
|
|
usersPubkey: undefined
|
|
})
|
|
)
|
|
}
|
|
|
|
private createAndSaveAuthToken(signedAuthEvent: SignedEvent) {
|
|
const base64Encoded = base64EncodeSignedEvent(signedAuthEvent)
|
|
|
|
// save newly created auth token (base64 nostr singed event) in local storage along with expiry time
|
|
saveAuthToken(base64Encoded)
|
|
return base64Encoded
|
|
}
|
|
}
|