Skip to content

Commit

Permalink
add ProfileValidator to profile endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexNi245 committed Aug 28, 2024
1 parent c001ae9 commit 1a437a5
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 36 deletions.
2 changes: 2 additions & 0 deletions packages/offchain-resolver/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
"@dm3-org/dm3-lib-crypto": "workspace:^",
"@dm3-org/dm3-lib-profile": "workspace:^",
"@dm3-org/dm3-lib-shared": "workspace:^",
"@dm3-org/dm3-lib-test-helper": "workspace:^",
"@erc725/erc725.js": "^0.27.1",
"@prisma/client": "^4.15.0",
"ajv": "^8.16.0",
"body-parser": "^1.20.1",
Expand Down
62 changes: 38 additions & 24 deletions packages/offchain-resolver/src/http/profile.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ describe('Profile', () => {
},
);

const luksoProvider: ethers.providers.JsonRpcProvider = {
//Make the otherwise empty object a valid Provider
_isProvider: true,
} as any;

beforeEach(async () => {
prismaClient = await getDbClient();
db = await getDatabase(prismaClient);
Expand Down Expand Up @@ -72,7 +77,7 @@ describe('Profile', () => {

describe('Create Alias', () => {
it('Rejects if there is no Profile', async () => {
app.use(profile(provider));
app.use(profile(provider, luksoProvider));
const { status, body } = await request(app)
.post(`/name`)
.send({
Expand All @@ -88,7 +93,7 @@ describe('Profile', () => {
});

it('Rejects invalid signature', async () => {
app.use(profile(provider));
app.use(profile(provider, luksoProvider));

const offChainProfile1 = app.locals.forTests;

Expand Down Expand Up @@ -122,10 +127,13 @@ describe('Profile', () => {

it('Rejects address with an empty eth balance', async () => {
app.use(
profile({
getBalance: async () => ethers.BigNumber.from(0),
resolveName: async () => offChainProfile.signer,
} as any),
profile(
{
getBalance: async () => ethers.BigNumber.from(0),
resolveName: async () => offChainProfile.signer,
} as any,
luksoProvider,
),
);
const offChainProfile = app.locals.forTests;
await request(app)
Expand Down Expand Up @@ -155,7 +163,7 @@ describe('Profile', () => {
});

it('Rejects if subdomain is already claimed', async () => {
app.use(profile(provider));
app.use(profile(provider, luksoProvider));
const profile2: UserProfile = {
publicSigningKey: '',
publicEncryptionKey: '',
Expand Down Expand Up @@ -196,10 +204,13 @@ describe('Profile', () => {
app2.use(bodyParser.json());

app2.use(
profile({
getBalance: async () => ethers.BigNumber.from(1),
resolveName: async () => app.locals.forTests.signer,
} as any),
profile(
{
getBalance: async () => ethers.BigNumber.from(1),
resolveName: async () => app.locals.forTests.signer,
} as any,
luksoProvider,
),
);
app2.locals.config = { spamProtection: true };
app2.locals.db = db;
Expand All @@ -222,7 +233,7 @@ describe('Profile', () => {

describe('Store UserProfile by address', () => {
it('Rejects invalid schema', async () => {
app.use(profile(provider));
app.use(profile(provider, luksoProvider));
const { status, body } = await request(app).post(`/address`).send({
address: SENDER_ADDRESS,
signedUserProfile: {},
Expand All @@ -232,7 +243,7 @@ describe('Profile', () => {
expect(body.error).to.equal('invalid schema');
});
it('Rejects invalid profile', async () => {
app.use(profile(provider));
app.use(profile(provider, luksoProvider));
const userProfile: UserProfile = {
publicSigningKey:
'0ekgI3CBw2iXNXudRdBQHiOaMpG9bvq9Jse26dButug=',
Expand Down Expand Up @@ -261,7 +272,7 @@ describe('Profile', () => {
});

it('Rejects if subdomain has already a profile', async () => {
app.use(profile(provider));
app.use(profile(provider, luksoProvider));

const offChainProfile1 = await getSignedUserProfile();

Expand Down Expand Up @@ -295,7 +306,7 @@ describe('Profile', () => {
expect(res2.body.error).to.eql('subdomain already claimed');
});
it('Rejects if subdomain is not supported', async () => {
app.use(profile(provider));
app.use(profile(provider, luksoProvider));

const offChainProfile1 = await getSignedUserProfile();

Expand Down Expand Up @@ -332,7 +343,7 @@ describe('Profile', () => {
});

it('Stores a valid profile', async () => {
app.use(profile(provider));
app.use(profile(provider, luksoProvider));
const {
signer,
profile: userProfile,
Expand Down Expand Up @@ -366,10 +377,13 @@ describe('Profile', () => {
app.locals.config.spamProtection = false;

app.use(
profile({
...provider,
resolveName: async () => signer,
} as any),
profile(
{
...provider,
resolveName: async () => signer,
} as any,
luksoProvider,
),
);

const writeRes = await request(app)
Expand Down Expand Up @@ -410,21 +424,21 @@ describe('Profile', () => {
});
describe('Get User By Account', () => {
it('Returns 400 if address in invalid', async () => {
app.use(profile(provider));
app.use(profile(provider, luksoProvider));
const { status, body } = await request(app).get(`/fooo`).send();
expect(status).to.equal(400);
});

it('Returns 404 if profile does not exists', async () => {
app.use(profile(provider));
app.use(profile(provider, luksoProvider));
const { status, body } = await request(app)
.get(`/${SENDER_ADDRESS}`)
.send();
expect(status).to.equal(404);
});

it('Rejcts invalid name subdomain', async () => {
app.use(profile(provider));
app.use(profile(provider, luksoProvider));
const {
signer,
profile: userProfile,
Expand Down Expand Up @@ -461,7 +475,7 @@ describe('Profile', () => {
});

it('Returns the profile linked to ', async () => {
app.use(profile(provider));
app.use(profile(provider, luksoProvider));
const {
signer,
profile: userProfile,
Expand Down
20 changes: 14 additions & 6 deletions packages/offchain-resolver/src/http/profile.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { checkSignature } from '@dm3-org/dm3-lib-crypto';
import { checkUserProfileWithAddress, schema } from '@dm3-org/dm3-lib-profile';
import { globalConfig, validateSchema } from '@dm3-org/dm3-lib-shared';
import { validateSchema } from '@dm3-org/dm3-lib-shared';
import { ethers } from 'ethers';
import express from 'express';
import { SiweMessage } from 'siwe';
import { ProfileValidator } from './profileValidator/ProfileValidator';
import { SubdomainManager } from './subdomainManager/SubdomainManager';
import { WithLocals } from './types';

export function profile(web3Provider: ethers.providers.BaseProvider) {
export function profile(
web3Provider: ethers.providers.BaseProvider,
luksoProvider: ethers.providers.BaseProvider,
) {
const router = express.Router();
//subdomain manager for address domains
const addressSubdomainManager = new SubdomainManager(
Expand Down Expand Up @@ -257,13 +261,17 @@ export function profile(web3Provider: ethers.providers.BaseProvider) {
return res.status(400).send({ error: 'invalid schema' });
}

const profileIsValid = checkUserProfileWithAddress(
signedUserProfile,
address,
);
//Check if the profile was signed by the owner of the address or an UP
const profileIsValid = await new ProfileValidator(
luksoProvider,
).validate(signedUserProfile, address);

//add check for lukso

//Check if profile sig is correcet
if (!profileIsValid) {
console.error('profile signature invalid');
console.error(signedUserProfile, address);
return res.status(400).send({ error: 'invalid profile' });
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ import {
MockedUserProfile,
mockUserProfile,
} from '@dm3-org/dm3-lib-test-helper';
import abiJson from './deployedAbi.json';
import { expect } from 'chai';
import { ethers } from 'ethers';
import { DM3_PROFILE_KEY } from '../../../../lib/smart-account/dist/KeyStore/constants';
import { ProfileValidator } from './ProfileValidator';

describe('ProfileValidator', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import { ethers } from 'ethers';
const ERC1271_SUCCESSVALUE = '0x1626ba7e';

export class ProfileValidator {
private readonly luksoProvider: ethers.providers.Web3Provider;
constructor(luksoProvider: ethers.providers.Web3Provider) {
private readonly luksoProvider: ethers.providers.BaseProvider;
constructor(luksoProvider: ethers.providers.BaseProvider) {
this.luksoProvider = luksoProvider;
}
//Check if a profile is signed by the owner of the address
Expand Down
4 changes: 3 additions & 1 deletion packages/offchain-resolver/src/http/resolverEndpoint.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ describe('Resolver Endpoint', () => {
resolveName: async () => profileApp.locals.forTests.signer,
};

profileApp.use(profile(provider));
const luksoProvider: ethers.providers.JsonRpcProvider = {} as any;

profileApp.use(profile(provider, luksoProvider));
profileApp.locals.db = db;
profileApp.locals.config = { spamProtection: true };
});
Expand Down
3 changes: 2 additions & 1 deletion packages/offchain-resolver/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import http from 'http';
import { resolverEndpoint } from './http/resolverEndpoint';
import { getDatabase } from './persistence/getDatabase';
import { getWeb3Provider } from './utils/getWeb3Provider';
import { getLuksoProvider } from './utils/getLuksoProvider';

import { profile } from './http/profile';

Expand All @@ -29,7 +30,7 @@ app.use(bodyParser.json());
};

app.use('/', resolverEndpoint());
app.use('/profile', profile(getWeb3Provider()));
app.use('/profile', profile(getWeb3Provider(), getLuksoProvider()));
})();
const port = process.env.PORT || '8081';
server.listen(port, () => {
Expand Down
7 changes: 7 additions & 0 deletions packages/offchain-resolver/src/utils/getLuksoProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { ethers } from 'ethers';
import { readKeyFromEnv } from './readKeyEnv';

export function getLuksoProvider(): ethers.providers.BaseProvider {
const rpc = readKeyFromEnv('LUKSO_RPC');
return new ethers.providers.JsonRpcProvider(rpc);
}

0 comments on commit 1a437a5

Please sign in to comment.