diff --git a/.eslintrc b/.eslintrc
index fbe62fc23..ba354ab30 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -21,11 +21,11 @@
"@typescript-eslint"
],
"rules": {
- "indent": ["error", 4],
+ "indent": ["error", 2],
"semi": ["error", "never"],
"quotes": ["error", "single"],
"vue/multi-word-component-names": "off",
- "max-len": ["error", { "code": 150 }],
+ "max-len": ["error", { "code": 999 }]
},
"ignorePatterns": [
"contracts/**/scripts/resources",
diff --git a/.vscode/settings.json b/.vscode/settings.json
index d495832af..e291c25e3 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,26 +1,24 @@
{
- "editor.codeActionsOnSave": {
- "source.fixAll.eslint": true
- },
- "[html]": {
- "editor.defaultFormatter": "Vue.volar"
- },
- "[vue]": {
- "editor.defaultFormatter": "Vue.volar"
- },
- "[javascript]": {
- "editor.defaultFormatter": "vscode.typescript-language-features"
- },
- "[json]": {
- "editor.defaultFormatter": "vscode.json-language-features"
- },
- "eslint.validate": [
- "vue",
- "typescript"
- ],
- "css.lint.unknownAtRules": "ignore",
- "jupyter.notebookFileRoot": "${fileDirname}",
- "volar.inlayHints.eventArgumentInInlineHandlers": false,
- "eslint.format.enable": true,
- "eslint.run": "onType"
-}
\ No newline at end of file
+ "editor.codeActionsOnSave": {
+ "source.fixAll.eslint": true
+ },
+ "[html]": {
+ "editor.defaultFormatter": "Vue.volar"
+ },
+ "[vue]": {
+ "editor.defaultFormatter": "Vue.volar"
+ },
+ "[javascript]": {
+ "editor.defaultFormatter": "vscode.typescript-language-features"
+ },
+ "[json]": {
+ "editor.defaultFormatter": "vscode.json-language-features"
+ },
+ "eslint.validate": ["vue", "typescript"],
+ "css.lint.unknownAtRules": "ignore",
+ "jupyter.notebookFileRoot": "${fileDirname}",
+ "volar.inlayHints.eventArgumentInInlineHandlers": false,
+ "eslint.format.enable": true,
+ "eslint.run": "onType",
+ "terminal.integrated.defaultProfile.windows": ""
+}
diff --git a/apps/web/src/App.vue b/apps/web/src/App.vue
index 870eba0d8..e7de7f910 100644
--- a/apps/web/src/App.vue
+++ b/apps/web/src/App.vue
@@ -1,13 +1,15 @@
-
+
diff --git a/services/users/scripts/db.ts b/services/users/scripts/db.ts
index 30d500a04..401cc819a 100644
--- a/services/users/scripts/db.ts
+++ b/services/users/scripts/db.ts
@@ -9,60 +9,62 @@ import { JsonSchema, Schema, accountSchema, nonceSchema, operatorSchema, userSch
*/
void async function () {
- if (process.env.STAGE !== 'local') {
- await loadCredentials()
- const dbCredentials = await getSecret(`${process.env.PROJECT}-users-db-credentials-${process.env.STAGE}`)
- const { port: dbPort, host: dbHost, dbname: dbName, username: dbUser, password: dbPassword } = JSON.parse(dbCredentials as string)
- process.env.DB_HOST = dbHost
- process.env.DB_PORT = dbPort
- process.env.DB_NAME = dbName
- process.env.DB_USER = dbUser
- process.env.DB_PASSWORD = dbPassword
- const sessionsCredentials = await getSecret(`${process.env.PROJECT}-sessions-credentials-${process.env.STAGE}`)
- const { host: sessionsHost, key: sessionsKey } = JSON.parse(sessionsCredentials as string)
- process.env.SESSIONS_HOST = sessionsHost
- process.env.SESSIONS_KEY = sessionsKey
- }
+ if (process.env.STAGE !== 'local') {
+ await loadCredentials()
+ const dbCredentials = await getSecret(`${process.env.PROJECT}-users-db-credentials-${process.env.STAGE}`)
+ const { port: dbPort, host: dbHost, dbname: dbName, username: dbUser, password: dbPassword } = JSON.parse(dbCredentials as string)
+ process.env.DB_HOST = dbHost
+ process.env.DB_PORT = dbPort
+ process.env.DB_NAME = dbName
+ process.env.DB_USER = dbUser
+ process.env.DB_PASSWORD = dbPassword
+ const sessionsCredentials = await getSecret(`${process.env.PROJECT}-sessions-credentials-${process.env.STAGE}`)
+ const { host: sessionsHost, key: sessionsKey } = JSON.parse(sessionsCredentials as string)
+ process.env.SESSIONS_HOST = sessionsHost
+ process.env.SESSIONS_KEY = sessionsKey
+ }
- const resourceDir = './scripts'
+ const resourceDir = './scripts'
- const tableSchemas = {
- account: accountSchema,
- operator: operatorSchema,
- nonce: nonceSchema,
- user: userSchema,
- userAccount: userAccountSchema
- }
+ const tableSchemas = {
+ account: accountSchema,
+ operator: operatorSchema,
+ nonce: nonceSchema,
+ user: userSchema,
+ userAccount: userAccountSchema
+ }
- let sqlSchema = ''
- for (const table of Object.keys(tableSchemas)) {
- const tableSchema = tableSchemas[table] as JsonSchema
- const schema = new Schema(tableSchema)
- const postgresTable = schema.getPostgresTable()
- console.log(`${schema.getTitle()} JSON schema parsed to SQL`)
- sqlSchema += `${postgresTable}\n\n`
- }
+ let sqlSchema = ''
+ for (const table of Object.keys(tableSchemas)) {
+ const tableSchema = tableSchemas[table] as JsonSchema
+ const schema = new Schema(tableSchema)
+ const postgresTable = schema.getPostgresTable()
+ console.log(`${schema.getTitle()} JSON schema parsed to SQL`)
+ sqlSchema += `${postgresTable}\n\n`
+ }
- const sqlDir = `${resourceDir}/.out/sql`
- if (!fs.existsSync(sqlDir)) fs.mkdirSync(sqlDir, { recursive: true })
- fs.writeFileSync(`${sqlDir}/schema.sql`, sqlSchema)
+ const sqlDir = `${resourceDir}/.out/sql`
+ if (!fs.existsSync(sqlDir)) fs.mkdirSync(sqlDir, { recursive: true })
+ fs.writeFileSync(`${sqlDir}/schema.sql`, sqlSchema)
- const stackName = 'casimir-users-db'
- await run(`docker compose -p ${stackName} -f ${resourceDir}/docker-compose.yaml up -d`)
- let dbReady = false
- while (!dbReady) {
- const health = await run('docker inspect --format=\'{{lower .State.Health.Status}}\' postgres') as string
- dbReady = health.trim() === 'healthy'
- await new Promise(resolve => setTimeout(resolve, 2500))
- }
- const atlas = await run('which atlas') as string
- if (!atlas || atlas.includes('not found')) {
- if (os.platform() === 'darwin') {
- await run('echo y | brew install atlas')
- } else {
- throw new Error('Please install atlas using `curl -sSf https://atlasgo.sh | sh`')
- }
+ const stackName = 'casimir-users-db'
+ await run(`docker compose -p ${stackName} -f ${resourceDir}/docker-compose.yaml up -d`)
+ let dbReady = false
+ while (!dbReady) {
+ const health = await run('docker inspect --format=\'{{lower .State.Health.Status}}\' postgres') as string
+ dbReady = health.trim() === 'healthy'
+ await new Promise(resolve => setTimeout(resolve, 2500))
+ }
+ const atlas = await run('which atlas') as string
+ if (!atlas || atlas.includes('not found')) {
+ if (os.platform() === 'darwin') {
+ await run('echo y | brew install atlas')
+ } else {
+ throw new Error('Please install atlas using `curl -sSf https://atlasgo.sh | sh`')
}
+ }
- await run(`atlas schema apply --url "postgres://postgres:password@localhost:5432/users?sslmode=disable" --to "file://${sqlDir}/schema.sql" --dev-url "docker://postgres/15" --auto-approve`)
+ await run(
+ `atlas schema apply --url "postgres://postgres:password@localhost:5432/users?sslmode=disable" --to "file://
+ ${sqlDir}/schema.sql" --dev-url "docker://postgres/15" --auto-approve`)
}()
\ No newline at end of file
diff --git a/services/users/src/routes/user.ts b/services/users/src/routes/user.ts
index 8c9ab715b..0d6c02f67 100644
--- a/services/users/src/routes/user.ts
+++ b/services/users/src/routes/user.ts
@@ -4,259 +4,268 @@ import { SessionRequest } from 'supertokens-node/framework/express'
import useDB from '../providers/db'
const router = express.Router()
-const { addAccount, addOperator, getAccounts, getUserByAddress, getUserById, updateUserAddress, updateUserAgreedToTermsOfService, removeAccount } = useDB()
+const {
+ addAccount,
+ addOperator,
+ getAccounts,
+ getUserByAddress,
+ getUserById,
+ updateUserAddress,
+ updateUserAgreedToTermsOfService,
+ removeAccount
+} = useDB()
router.get('/', verifySession(), async (req: SessionRequest, res: express.Response) => {
- try {
- const id = req.session?.getUserId() as string
- console.log('getting user by id :>> ', id)
- const user = await getUserById(id)
- console.log('user in user home route :>> ', user)
- const message = user ? 'User found' : 'User not found'
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message,
- error: false,
- user
- })
- } catch (err) {
- res.status(500)
- res.json({
- message: 'Error getting user',
- error: true,
- user: null
- })
- }
+ try {
+ const id = req.session?.getUserId() as string
+ console.log('getting user by id :>> ', id)
+ const user = await getUserById(id)
+ console.log('user in user home route :>> ', user)
+ const message = user ? 'User found' : 'User not found'
+ res.setHeader('Content-Type', 'application/json')
+ res.status(200)
+ res.json({
+ message,
+ error: false,
+ user
+ })
+ } catch (err) {
+ res.status(500)
+ res.json({
+ message: 'Error getting user',
+ error: true,
+ user: null
+ })
+ }
})
router.post('/add-sub-account', verifySession(), async (req: SessionRequest, res: express.Response) => {
- try {
- console.log('ADDING ACCOUNT!')
- const { account, id } = req.body
- const { ownerAddress } = account
- const userId = id.toString()
- const userSessionId = req.session?.getUserId()
- const validatedUserId = validateUserId(userSessionId, userId)
- console.log('validatedUserId :>> ', validatedUserId)
- if (!validatedUserId) {
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message: 'Address does not match session',
- error: true,
- data: null
- })
- }
- await addAccount(account)
- const user = await getUserByAddress(ownerAddress)
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message: 'Account added',
- error: false,
- data: user
- })
- } catch (err) {
- res.status(500)
- res.json({
- message: 'Error adding account',
- error: true,
- data: null
- })
+ try {
+ console.log('ADDING ACCOUNT!')
+ const { account, id } = req.body
+ const { ownerAddress } = account
+ const userId = id.toString()
+ const userSessionId = req.session?.getUserId()
+ const validatedUserId = validateUserId(userSessionId, userId)
+ console.log('validatedUserId :>> ', validatedUserId)
+ if (!validatedUserId) {
+ res.setHeader('Content-Type', 'application/json')
+ res.status(200)
+ res.json({
+ message: 'Address does not match session',
+ error: true,
+ data: null
+ })
}
+ await addAccount(account)
+ const user = await getUserByAddress(ownerAddress)
+ res.setHeader('Content-Type', 'application/json')
+ res.status(200)
+ res.json({
+ message: 'Account added',
+ error: false,
+ data: user
+ })
+ } catch (err) {
+ res.status(500)
+ res.json({
+ message: 'Error adding account',
+ error: true,
+ data: null
+ })
+ }
})
router.post('/add-operator', verifySession(), async (req: SessionRequest, res: express.Response) => {
- try {
- console.log('ADDING OPERATOR!')
- const { address, nodeUrl } = req.body
- const userId = parseInt(req.session?.getUserId() as string)
- const accounts = await getAccounts(address)
- const userAccount = accounts.find(account => parseInt(account.userId) === userId)
- const accountId = userAccount?.id as number
- await addOperator({ accountId, nodeUrl, userId })
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message: 'Operator added',
- error: false
- })
- } catch (err) {
- res.status(500)
- res.json({
- message: 'Error adding operator',
- error: true
- })
- }
+ try {
+ console.log('ADDING OPERATOR!')
+ const { address, nodeUrl } = req.body
+ const userId = parseInt(req.session?.getUserId() as string)
+ const accounts = await getAccounts(address)
+ const userAccount = accounts.find(account => parseInt(account.userId) === userId)
+ const accountId = userAccount?.id as number
+ await addOperator({ accountId, nodeUrl, userId })
+ res.setHeader('Content-Type', 'application/json')
+ res.status(200)
+ res.json({
+ message: 'Operator added',
+ error: false
+ })
+ } catch (err) {
+ res.status(500)
+ res.json({
+ message: 'Error adding operator',
+ error: true
+ })
+ }
})
router.get('/check-if-primary-address-exists/:provider/:address', async (req: express.Request, res: express.Response) => {
- try {
- const { params } = req
- const { address, provider } = params
- console.log('getting user by address')
- const user = await getUserByAddress(address)
- console.log('user in check-if-primary-.....:>> ', user)
- const userAddress = user?.address
- const userProvider = user?.walletProvider
- const sameAddress = userAddress === address
- const sameProvider = userProvider === provider
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- error: false,
- message: 'Successfully checked if primary address exists',
- data: {
- sameAddress,
- sameProvider
- }
- })
- } catch (error: any) {
- const { message } = error
- res.setHeader('Content-Type', 'application/json')
- res.status(500)
- res.json({
- error: true,
- message: message || 'Problem checking if primary address exists'
- })
- }
+ try {
+ const { params } = req
+ const { address, provider } = params
+ console.log('getting user by address')
+ const user = await getUserByAddress(address)
+ console.log('user in check-if-primary-.....:>> ', user)
+ const userAddress = user?.address
+ const userProvider = user?.walletProvider
+ const sameAddress = userAddress === address
+ const sameProvider = userProvider === provider
+ res.setHeader('Content-Type', 'application/json')
+ res.status(200)
+ res.json({
+ error: false,
+ message: 'Successfully checked if primary address exists',
+ data: {
+ sameAddress,
+ sameProvider
+ }
+ })
+ } catch (error: any) {
+ const { message } = error
+ res.setHeader('Content-Type', 'application/json')
+ res.status(500)
+ res.json({
+ error: true,
+ message: message || 'Problem checking if primary address exists'
+ })
+ }
})
router.get('/check-secondary-address/:address', async (req: express.Request, res: express.Response) => {
- try {
- const { params } = req
- const { address } = params
- const accounts = await getAccounts(address)
- const users = await Promise.all(accounts.map(async account => {
- const { userId } = account
- const user = await getUserById(userId)
- const { address, walletProvider } = user
- return {
- address: maskAddress(address),
- walletProvider,
- }
- }))
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- error: false,
- message: 'Successfully checked secondary address',
- data: users
- })
- } catch (error: any) {
- console.log('error in /check-secondary-address :>> ', error)
- res.setHeader('Content-Type', 'application/json')
- res.status(500)
- res.json({
- error: true,
- message: error.message || 'Problem checking secondary address'
- })
- }
+ try {
+ const { params } = req
+ const { address } = params
+ const accounts = await getAccounts(address)
+ const users = await Promise.all(accounts.map(async account => {
+ const { userId } = account
+ const user = await getUserById(userId)
+ const { address, walletProvider } = user
+ return {
+ address: maskAddress(address),
+ walletProvider,
+ }
+ }))
+ res.setHeader('Content-Type', 'application/json')
+ res.status(200)
+ res.json({
+ error: false,
+ message: 'Successfully checked secondary address',
+ data: users
+ })
+ } catch (error: any) {
+ console.log('error in /check-secondary-address :>> ', error)
+ res.setHeader('Content-Type', 'application/json')
+ res.status(500)
+ res.json({
+ error: true,
+ message: error.message || 'Problem checking secondary address'
+ })
+ }
})
router.post('/remove-sub-account', verifySession(), async (req: SessionRequest, res: express.Response) => {
- try {
- console.log('REMOVING ACCOUNT!')
- const { address, currency, id, ownerAddress, walletProvider } = req.body
- const userId = id.toString()
- const userSessionId = req.session?.getUserId()
- const validatedAddress = validateUserId(userSessionId, userId)
- if (!validatedAddress) {
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message: 'Address does not match session',
- error: true,
- data: null
- })
- return
- }
- const accountRemoved = await removeAccount({ address, currency, ownerAddress, walletProvider })
- const user = await getUserByAddress(ownerAddress)
+ try {
+ console.log('REMOVING ACCOUNT!')
+ const { address, currency, id, ownerAddress, walletProvider } = req.body
+ const userId = id.toString()
+ const userSessionId = req.session?.getUserId()
+ const validatedAddress = validateUserId(userSessionId, userId)
+ if (!validatedAddress) {
+ res.setHeader('Content-Type', 'application/json')
+ res.status(200)
+ res.json({
+ message: 'Address does not match session',
+ error: true,
+ data: null
+ })
+ return
+ }
+ const accountRemoved = await removeAccount({ address, currency, ownerAddress, walletProvider })
+ const user = await getUserByAddress(ownerAddress)
- if (accountRemoved) {
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message: 'Account removed',
- error: false,
- data: user
- })
- } else {
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message: 'Account not found',
- error: true,
- data: user
- })
- }
- } catch (err) {
- console.log('err :>> ', err)
- res.status(500)
- res.json({
- message: 'Error adding account',
- error: true
- })
+ if (accountRemoved) {
+ res.setHeader('Content-Type', 'application/json')
+ res.status(200)
+ res.json({
+ message: 'Account removed',
+ error: false,
+ data: user
+ })
+ } else {
+ res.setHeader('Content-Type', 'application/json')
+ res.status(200)
+ res.json({
+ message: 'Account not found',
+ error: true,
+ data: user
+ })
}
+ } catch (err) {
+ console.log('err :>> ', err)
+ res.status(500)
+ res.json({
+ message: 'Error adding account',
+ error: true
+ })
+ }
})
// TODO: Think through handling changing primary address with SuperTokens Sessions.
router.put('/update-primary-account', verifySession(), async (req: SessionRequest, res: express.Response) => {
- const { userId } = req.body
- let { updatedAddress } = req.body
- updatedAddress = updatedAddress.toLowerCase()
+ const { userId } = req.body
+ let { updatedAddress } = req.body
+ updatedAddress = updatedAddress.toLowerCase()
- const user = await updateUserAddress(userId, updatedAddress)
- if (!user) {
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message: 'User not found',
- error: true,
- data: null
- })
- } else {
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message: 'Primary account updated',
- error: false,
- data: user
- })
- }
+ const user = await updateUserAddress(userId, updatedAddress)
+ if (!user) {
+ res.setHeader('Content-Type', 'application/json')
+ res.status(200)
+ res.json({
+ message: 'User not found',
+ error: true,
+ data: null
+ })
+ } else {
+ res.setHeader('Content-Type', 'application/json')
+ res.status(200)
+ res.json({
+ message: 'Primary account updated',
+ error: false,
+ data: user
+ })
+ }
})
router.put('/update-user-agreement/:userId', verifySession(), async (req: SessionRequest, res: express.Response) => {
- try {
- const { agreed } = req.body
- const { userId } = req.params
- const userID = parseInt(userId)
- const user = await updateUserAgreedToTermsOfService(userID, agreed)
- res.setHeader('Content-Type', 'application/json')
- res.status(200)
- res.json({
- message: 'User agreement updated',
- error: false,
- data: user
- })
- } catch (err) {
- res.status(500)
- res.json({
- message: 'Error updating user agreement',
- error: true,
- data: null
- })
- }
+ try {
+ const { agreed } = req.body
+ const { userId } = req.params
+ const userID = parseInt(userId)
+ const user = await updateUserAgreedToTermsOfService(userID, agreed)
+ res.setHeader('Content-Type', 'application/json')
+ res.status(200)
+ res.json({
+ message: 'User agreement updated',
+ error: false,
+ data: user
+ })
+ } catch (err) {
+ res.status(500)
+ res.json({
+ message: 'Error updating user agreement',
+ error: true,
+ data: null
+ })
+ }
})
function maskAddress(address: string) {
- return address.slice(0, 6) + '...' + address.slice(-4)
+ return address.slice(0, 6) + '...' + address.slice(-4)
}
function validateUserId(userSessionId:string | undefined, userId:string) {
- return userSessionId === userId
+ return userSessionId === userId
}
export default router
\ No newline at end of file