sigit.io/src/controllers/AuthController.ts
enes 6652c6519e
Some checks failed
Open PR on Staging / audit_and_check (pull_request) Failing after 9s
refactor(review): add date util functions
2024-08-13 11:52:05 +02:00

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
}
}