Skip to content

Commit

Permalink
Add tests for AWS Verify endpoint (#1199)
Browse files Browse the repository at this point in the history
* Add tests for AWS Verify endpoint

* undo site key change

* Fix server URL

* Fix getPair function

* package-lock.json

* remove missing export

* solver service in util

* npm i

* Fix URL in client-example config

* Add different verify types into server example

* remove extra env var and remove debug from vite run

* Allow setting cwd for updating env files

* Revert site key change

* remove log

* Create function for generating a secret
  • Loading branch information
forgetso authored May 7, 2024
1 parent 2b032f3 commit cf47f6b
Show file tree
Hide file tree
Showing 35 changed files with 176 additions and 29,789 deletions.
4 changes: 3 additions & 1 deletion demos/client-example-server/env.development
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
PROSOPO_VERIFY_ENDPOINT=http://localhost:9237/dev/siteverify
PROSOPO_VERIFICATION_TYPE=local
PROSOPO_SITE_KEY=5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw
PROSOPO_SUBSTRATE_ENDPOINT=ws://localhost:9944
PROSOPO_CONTRACT_ADDRESS=
Expand All @@ -8,4 +10,4 @@ PROSOPO_SERVER_PORT=9228
PROSOPO_DEFAULT_ENVIRONMENT=development
PROSOPO_DEFAULT_NETWORK=development
PROSOPO_MONGO_EVENTS_URI=mongodb+srv://<MONGO_URI_HERE>/frictionless_events
_DEV_ONLY_WATCH_EVENTS=false
_DEV_ONLY_WATCH_EVENTS=false
15 changes: 14 additions & 1 deletion demos/client-example-server/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,23 @@ export function getEnvFile(filename = '.env', filepath = './') {
return path.join(filepath, `${filename}.${env}`)
}

enum ProsopoVerificationType {
api = 'api',
local = 'local',
}

async function main() {
const logger = getLoggerDefault()
loadEnv()

const verifyEndpoint = process.env.PROSOPO_VERIFY_ENDPOINT || 'https://api.prosopo.io/siteverify'

const verifyType: ProsopoVerificationType = Object.keys(ProsopoVerificationType).includes(
process.env.PROSOPO_VERIFICATION_TYPE as string
)
? (process.env.PROSOPO_VERIFICATION_TYPE as ProsopoVerificationType)
: ProsopoVerificationType.api

const app = express()

app.use(cors({ origin: true, credentials: true }))
Expand Down Expand Up @@ -72,7 +85,7 @@ async function main() {
const pair = await getPairAsync(config.networks[config.defaultNetwork], process.env.PROSOPO_SITE_PRIVATE_KEY)
const prosopoServer = new ProsopoServer(config, pair)

app.use(routesFactory(mongoose, prosopoServer))
app.use(routesFactory(mongoose, prosopoServer, verifyEndpoint, verifyType))

app.listen(process.env.PROSOPO_SERVER_PORT)
}
Expand Down
53 changes: 49 additions & 4 deletions demos/client-example-server/src/controllers/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { ApiParams } from '@prosopo/types'
import { ApiParams, ProcaptchaOutput, ProcaptchaOutputSchema } from '@prosopo/types'
import { Connection } from 'mongoose'
import { NextFunction, Request, Response } from 'express'
import { ProcaptchaResponse } from '@prosopo/types'
Expand All @@ -35,9 +35,34 @@ function hashPassword(password: string): string {
return u8aToHex(blake2b(password))
}

const verify = async (
prosopoServer: ProsopoServer,
verifyType: string,
verifyEndpoint: string,
data: ProcaptchaOutput
) => {
if (verifyType === 'api') {
// verify using the API endpoint
console.log('verifying using the API endpoint')

const response = await fetch(verifyEndpoint, {
method: 'POST',
body: JSON.stringify(data),
})
return (await response.json()).verified
} else {
// verify using the TypeScript library
console.log('verifying using the TypeScript library')

return await prosopoServer.isVerified(data)
}
}

const signup = async (
mongoose: Connection,
prosopoServer: ProsopoServer,
verifyEndpoint: string,
verifyType: string,
req: Request,
res: Response,
next: NextFunction
Expand All @@ -54,7 +79,15 @@ const signup = async (
return res.status(409).json({ message: 'email already exists' })
}
console.log('payload', payload)
if (await prosopoServer.isVerified(payload[ApiParams.procaptchaResponse])) {

// get the contents of the procaptcha-response JSON data
const data = ProcaptchaOutputSchema.parse(payload[ApiParams.procaptchaResponse])

console.log('sending data', data)

const verified = await verify(prosopoServer, verifyType, verifyEndpoint, data)

if (verified) {
// salt
const salt = randomAsHex(32)
// !!!DUMMY CODE!!! - Do not use in production. Use bcrypt or similar for password hashing.
Expand Down Expand Up @@ -83,7 +116,14 @@ const signup = async (
}
}

const login = async (mongoose: Connection, prosopoServer: ProsopoServer, req: Request, res: Response) => {
const login = async (
mongoose: Connection,
prosopoServer: ProsopoServer,
verifyEndpoint: string,
verifyType: string,
req: Request,
res: Response
) => {
const User = mongoose.model<UserInterface>('User')
await prosopoServer.isReady()
// checks if email exists
Expand All @@ -95,7 +135,12 @@ const login = async (mongoose: Connection, prosopoServer: ProsopoServer, req: Re
res.status(404).json({ message: 'user not found' })
} else {
const payload = SubscribeBodySpec.parse(req.body)
if (await prosopoServer.isVerified(payload[ApiParams.procaptchaResponse])) {

const data = ProcaptchaOutputSchema.parse(payload[ApiParams.procaptchaResponse])

const verified = await verify(prosopoServer, verifyType, verifyEndpoint, data)

if (verified) {
// password hash
// !!!DUMMY CODE!!! - Do not use in production. Use bcrypt or similar for password hashing.
const passwordHash = hashPassword(`${req.body.password}${dbUser.salt}`)
Expand Down
11 changes: 8 additions & 3 deletions demos/client-example-server/src/routes/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@ import express from 'express'

const router = express.Router()

function getRoutes(mongoose: Connection, prosopoServer: ProsopoServer): express.Router {
router.post('/login', login.bind(null, mongoose, prosopoServer))
function getRoutes(
mongoose: Connection,
prosopoServer: ProsopoServer,
verifyEndpoint: string,
verifyType: string
): express.Router {
router.post('/login', login.bind(null, mongoose, prosopoServer, verifyEndpoint, verifyType))

router.post('/signup', signup.bind(null, mongoose, prosopoServer))
router.post('/signup', signup.bind(null, mongoose, prosopoServer, verifyEndpoint, verifyType))

router.get('/private', isAuth)

Expand Down
2 changes: 1 addition & 1 deletion demos/client-example/env.development
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ PROSOPO_SITE_KEY=5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw
PROSOPO_SUBSTRATE_ENDPOINT=ws://127.0.0.1:9944
PROSOPO_CONTRACT_ADDRESS=
PROSOPO_WEB2=true
PROSOPO_SERVER_URL=http://localhost:9228
PROSOPO_SERVER_URL=http://localhost
PROSOPO_PORT=9230
PROSOPO_DEFAULT_NETWORK=development
PROSOPO_DEFAULT_ENVIRONMENT=development
Expand Down
5 changes: 3 additions & 2 deletions demos/client-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@
"@prosopo/procaptcha": "0.3.39",
"@prosopo/procaptcha-frictionless": "0.3.39",
"@prosopo/procaptcha-react": "0.3.39",
"@prosopo/server": "0.3.39",
"@prosopo/types": "0.3.39",
"@types/react-dom": "^18.2.4",
"electron": "25.8.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.22.3",
"web-vitals": "^2.1.4"
},
Expand Down
4 changes: 3 additions & 1 deletion demos/client-example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
import { ExtensionAccountSelect } from './components/ExtensionAccountSelect.js'
import { Procaptcha } from '@prosopo/procaptcha-react'
import { ProcaptchaFrictionless } from '@prosopo/procaptcha-frictionless'
import { getServerUrl } from '@prosopo/server'
import { useState } from 'react'

const corsHeaders = {
Expand Down Expand Up @@ -55,10 +56,11 @@ function App(props: AppProps) {
dappName: 'client-example',
defaultEnvironment:
(process.env.PROSOPO_DEFAULT_ENVIRONMENT as EnvironmentTypes) || EnvironmentTypesSchema.enum.development,
serverUrl: process.env.PROSOPO_SERVER_URL || 'localhost:9228',
serverUrl: getServerUrl(),
mongoAtlasUri: process.env.PROSOPO_MONGO_EVENTS_URI || '',
devOnlyWatchEvents: process.env._DEV_ONLY_WATCH_EVENTS === 'true' || false,
})
console.log(config)

const label = isLogin ? 'Login' : 'Sign up'
const urlPath = isLogin ? 'login' : 'signup'
Expand Down
6 changes: 6 additions & 0 deletions demos/client-example/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,15 @@
{
"path": "../../packages/procaptcha-react"
},
{
"path": "../../packages/procaptcha-frictionless"
},
{
"path": "../../packages/cli"
},
{
"path": "../../packages/types"
},
{
"path": "../../dev/config"
},
Expand Down
4 changes: 2 additions & 2 deletions demos/client-frictionless-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
"@prosopo/types": "0.3.39",
"@types/react-dom": "^18.2.4",
"electron": "25.8.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"web-vitals": "^2.1.4",
"@prosopo/procaptcha-pow": "0.3.39"
},
Expand Down
4 changes: 2 additions & 2 deletions demos/client-pow-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
"@prosopo/types": "0.3.39",
"@types/react-dom": "^18.2.4",
"electron": "25.8.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"web-vitals": "^2.1.4",
"@prosopo/procaptcha-pow": "0.3.39"
},
Expand Down
4 changes: 2 additions & 2 deletions dev/config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@
"eslint-plugin-unused-imports": "^2.0.0",
"glob": "^10.0.0",
"path-scurry": "^1.10.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"regenerator-runtime": "^0.14.0",
"rollup-plugin-cleanup": "^3.2.1",
"rollup-plugin-import-css": "^3.5.0",
Expand Down
1 change: 1 addition & 0 deletions dev/scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"@prosopo/util": "0.3.39",
"consola": "^3.2.3",
"dotenv": "^16.0.3",
"fast-glob": "^3.3.2",
"glob": "^10.0.0",
"qs": "^6.11.2",
"varuint-bitcoin": "^1.1.2",
Expand Down
13 changes: 10 additions & 3 deletions dev/scripts/src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,23 @@ export async function processArgs(args: string[]) {
yargs
.option('update_env', {
type: 'boolean',
demand: false,
demandOption: false,
desc: 'Update env files with the new contract address',
default: false,
})
.option('deployer', {
type: 'string',
demand: false,
demandOption: false,
desc: `The account prefix that will deploy the contract. Specifying PROVIDER will cause the
script to look for PROVIDER_JSON in the env file. Specifying DEPLOYER will cause the script to
look for DEPLOYER_JSON in the env file. Defaults to undefined.`,
default: undefined,
})
.option('cwd', {
type: 'string',
demandOption: false,
desc: `The working directory from which env files will be updated`,
default: undefined,
}),
async (argv) => {
const protocolContractAddress = await deployProtocol(
Expand All @@ -70,7 +76,8 @@ export async function processArgs(args: string[]) {
await updateEnvFiles(
['PROSOPO_CONTRACT_ADDRESS', 'NEXT_PUBLIC_PROSOPO_CONTRACT_ADDRESS'],
protocolContractAddress.toString(),
log
log,
argv.cwd
)
}
},
Expand Down
18 changes: 9 additions & 9 deletions dev/scripts/src/util/updateEnv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,32 @@
import { Logger } from '@prosopo/common'
import { at } from '@prosopo/util'
import { getEnv } from '@prosopo/cli'
import { glob } from 'glob'
import dotenv from 'dotenv'
import fg from 'fast-glob'
import fs from 'fs'
import path from 'path'

const ignore = [
'node_modules/**',
'**/node_modules/**',
'node_modules/**',
'../../**/node_modules/**',
'../node_modules/**',
'../../node_modules/**',
]
const __dirname = path.resolve()
export async function findEnvFiles(logger: Logger) {
export async function findEnvFiles(logger: Logger, cwd?: string) {
const env = getEnv()
const fileName = `.env.${env}`
// options is optional
logger.info('Searching for files')
return await glob.glob(`../../**/${fileName}`, {
ignore: ignore,
return await fg(`${cwd || '../..'}/**/${fileName}`, {
ignore,
})
}

export async function updateDemoHTMLFiles(varMatchers: RegExp[], varValue: string, logger: Logger) {
// replace the site key in the html files
const files = await glob.glob('../../demos/**/*.html', {
const files = await fg('../../demos/**/*.html', {
ignore: ignore,
})
logger.info('HTML files found', files)
Expand Down Expand Up @@ -67,14 +67,14 @@ export async function updateDemoHTMLFiles(varMatchers: RegExp[], varValue: strin
})
}

export async function updateEnvFiles(varNames: string[], varValue: string, logger: Logger) {
const files = await findEnvFiles(logger)
export async function updateEnvFiles(varNames: string[], varValue: string, logger: Logger, cwd?: string) {
const files = await findEnvFiles(logger, cwd)
logger.info('Env files found', files)
files.forEach((file) => {
let write = false
// the following code loads a .env file, searches for the variable and replaces it
// then saves the file
const filePath = path.resolve(process.cwd(), file)
const filePath = path.resolve(cwd || process.cwd(), file)
const envConfig = dotenv.parse(fs.readFileSync(filePath))
for (const varName of varNames) {
if (varName in envConfig) {
Expand Down
1 change: 1 addition & 0 deletions dev/vite-plugin-watch-workspace/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"license": "Apache-2.0",
"dependencies": {
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"vite": "^5.1.7"
},
"devDependencies": {
Expand Down
Loading

0 comments on commit cf47f6b

Please sign in to comment.