@startuml uc01
title "Use Case #1: Create Account"


'Styling goes here
hide footbox
skinparam stereotypePosition bottom
skinparam sequenceMessageAlign direction
skinparam sequence {
	LifeLineBorderColor #Silver
	LifeLineBackgroundColor #Gainsboro
}

'Setup the objects involved here
actor User as u <<Actor>>
boundary App as a <<Boundary>>
boundary RegistrationWindow as rw <<Boundary>>
control CryptoAPI as ca <<Control>>
control VaultManager as vm <<Control>>
entity Vault as v <<Entity>>
control RegisterUserRoute as rur <<Control>>
control DatabaseManager as db <<Control>>
boundary SMTPClient as sc <<Boundary>>

'Setup persistent objects here
activate u 
activate a
activate ca
activate vm
activate rur
activate db
activate sc

'--- FLOW OF CONTROL STARTS HERE ---
'User selects “Create Account” on the front page.
u -> a: Selects “Create Account” \nin the welcome window

'System shows a form to create the account.
a -> rw: show()
activate rw

'User enters email address, username. User clicks “Create Account” button.
u -> rw: Enters email and username \nand clicks "Create account"
rw -> rw: validate(formData)

'User’s device generates a UUID for the user and vault, timestamp, crypto key pair, and an identifier for the vault.
rw -> ca: ed25519Keygen()
ca --> rw: return: PrivateKey, PublicKey objects
rw -> rw: generateVaultId() -> vaultId

'User’s device sends the UUID of the user, timestamp, and generated public key to the server. The private key stays on the device for security reasons (CRITICAL).
rw -> rur: POST /api/users/register json::{user_info}

'Server checks if the account already exists
rur -> rur: check validity of \nusername, email, pubkey
rur -> db: QUERY username|email

group User exists
	db --> rur: return: username exists || email exists
	rur --> rw: RESP json::{error, user_already_exists}
	rw -> u: show error stating \nuser already exists
	rnote over u
	Flow of control prematurely ends here
	if the provided email or username is
	already in the database.
	endrnote
end

group User doesn't exist
	'Server creates the user and issues a temporary access token
	db --> rur: return: no record for username or email
	rur -> rur: createUser(options) -> user
	rur -> rur: createTempAuthToken() -> token \nuser.tokens.append(token)
	rur -> db: PUT user
	rur -> rur: generateChallenges(email, pk) -> eChall, pkChall

	'Server sends an email to the user to confirm creation of the account.
	rur -> rur: composeEmail(eChall) -> emailContent
	rur -> sc: sendEmail(user.email, emailContent)
	rur -> db: PUT eChall, pkChall

	'Server sends the response back and it's confirmed.
	rur --> rw: RESP json::{success, user.id, redact(user.email), challengeIDs, token}
	rw -> u: show account details plus instructions \non how to complete challenges
	u -> rw: clicks "Confirm Account Creation"
end

rnote over u
Email verification via "Use Case #8" can
occur asynchronously after this point.
endrnote

'User’s device creates a vault with the details provided by the user and the data that was generated.
rw -> vm: createNewVault(vaultId, sk, pk)
vm --> v: create: Vault
activate v
vm --> rw: return: Vault object

== "Use Case #7: Encrypt Vault" is called to store the vault to the device ==

'User begins the challenge process
rw -> u: prompts to verify\n public key
u -> rw: clicks "Verify Public Key"

== "Use Case #8: Challenge User" is called to validate the public key ==

'In-app challenges are completed
rw -> u: shows that the public \nkey was validated
u -> rw: clicks "Complete Registration"
rw -> vm: destroy()
deactivate rw
vm -> v: destroy()
deactivate v

'Cleanup
a -> u: shows welcome window once again
'--- FLOW OF CONTROL ENDS HERE   ---

@enduml
