sigit.io/src/controllers/AuthController.ts

133 lines
3.4 KiB
TypeScript
Raw Normal View History

import { EventTemplate } from 'nostr-tools'
import { MetadataController, NostrController } from '.'
import {
setAuthState,
setMetadataEvent,
setRelayMapAction
} from '../store/actions'
import store from '../store/store'
2024-03-19 15:27:18 +05:00
import {
base64DecodeAuthToken,
base64EncodeSignedEvent,
getAuthToken,
getVisitedLink,
saveAuthToken,
compareObjects
2024-03-19 15:27:18 +05:00
} from '../utils'
import { appPrivateRoutes } from '../routes'
2024-03-20 09:44:10 +05:00
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 = Math.floor(Date.now() / 1000)
const { hostname } = window.location
const authEvent: EventTemplate = {
kind: 1,
tags: [],
content: `${hostname}-${timestamp}`,
created_at: timestamp
}
2024-03-19 15:27:18 +05:00
const signedAuthEvent = await this.nostrController.signEvent(authEvent)
this.createAndSaveAuthToken(signedAuthEvent)
store.dispatch(
setAuthState({
2024-03-01 15:16:35 +05:00
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 visitedLink = getVisitedLink()
if (visitedLink) {
const { pathname, search } = visitedLink
return Promise.resolve(`${pathname}${search}`)
} else {
// Navigate user in
return Promise.resolve(appPrivateRoutes.homePage)
}
}
2024-03-19 15:27:18 +05:00
checkSession() {
const savedAuthToken = getAuthToken()
2024-03-20 09:44:10 +05:00
if (savedAuthToken) {
const signedEvent = base64DecodeAuthToken(savedAuthToken)
2024-03-19 15:27:18 +05:00
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
2024-03-20 09:44:10 +05:00
saveAuthToken(base64Encoded)
2024-03-19 15:27:18 +05:00
return base64Encoded
}
}