Skip to content

Commit

Permalink
add client input validation
Browse files Browse the repository at this point in the history
  • Loading branch information
josemarinas committed Sep 1, 2023
1 parent 4ebcb0f commit a57763b
Show file tree
Hide file tree
Showing 35 changed files with 3,448 additions and 182 deletions.
3 changes: 3 additions & 0 deletions modules/client-common/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ TEMPLATE:
-->

## [UPCOMING]
### Added
- Add common schemas for validations
## 1.5.0-rc0
### Changed
- Renamed `LIVE_CONTRACTS` properties

Expand Down
3 changes: 2 additions & 1 deletion modules/client-common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"@ethersproject/providers": "^5.5.0",
"@ethersproject/wallet": "^5.6.0",
"graphql": "^16.5.0",
"graphql-request": "^4.3.0"
"graphql-request": "^4.3.0",
"yup": "^1.2.0"
}
}
29 changes: 29 additions & 0 deletions modules/client-common/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { activeContractsList } from "@aragon/osx-ethers";
import { ProposalMetadata, SupportedNetwork } from "./types";
import { NetworkDeployment } from "./internal";
import { Network } from "@ethersproject/networks";
import { keccak256 } from "@ethersproject/keccak256";
import { toUtf8Bytes } from "@ethersproject/strings";

/** Timeout that will be applied to operations involving
* many fetch requests that could take a long time */
Expand Down Expand Up @@ -226,3 +228,30 @@ export const ADDITIONAL_NETWORKS: Network[] = [
chainId: 31337,
},
];

const Permissions = {
UPGRADE_PERMISSION: "UPGRADE_PERMISSION",
SET_METADATA_PERMISSION: "SET_METADATA_PERMISSION",
EXECUTE_PERMISSION: "EXECUTE_PERMISSION",
WITHDRAW_PERMISSION: "WITHDRAW_PERMISSION",
SET_SIGNATURE_VALIDATOR_PERMISSION: "SET_SIGNATURE_VALIDATOR_PERMISSION",
SET_TRUSTED_FORWARDER_PERMISSION: "SET_TRUSTED_FORWARDER_PERMISSION",
ROOT_PERMISSION: "ROOT_PERMISSION",
CREATE_VERSION_PERMISSION: "CREATE_VERSION_PERMISSION",
REGISTER_PERMISSION: "REGISTER_PERMISSION",
REGISTER_DAO_PERMISSION: "REGISTER_DAO_PERMISSION",
REGISTER_ENS_SUBDOMAIN_PERMISSION: "REGISTER_ENS_SUBDOMAIN_PERMISSION",
MINT_PERMISSION: "MINT_PERMISSION",
MERKLE_MINT_PERMISSION: "MERKLE_MINT_PERMISSION",
MODIFY_ALLOWLIST_PERMISSION: "MODIFY_ALLOWLIST_PERMISSION",
SET_CONFIGURATION_PERMISSION: "SET_CONFIGURATION_PERMISSION",
};

const PermissionIds = Object.entries(Permissions).reduce(
(acc, [k, v]) => ({ ...acc, [k + "_ID"]: keccak256(toUtf8Bytes(v)) }),
{} as { [k: string]: string },
);
Object.freeze(Permissions);
export { Permissions };
Object.freeze(PermissionIds);
export { PermissionIds };
1 change: 1 addition & 0 deletions modules/client-common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from "./context";
export * from "./constants";
export * from "./types";
export * from "./utils";
export * from "./schemas";
93 changes: 93 additions & 0 deletions modules/client-common/src/schemas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import {
InvalidAddressOrEnsError,
InvalidCidError,
InvalidContractAbiError,
InvalidParameter,
InvalidSubdomainError,
isEnsName,
isIpfsUri,
isSubdomain,
} from "@aragon/sdk-common";
import { array, mixed, number, object, string } from "yup";
import { isAddress } from "@ethersproject/address";

export const BigintSchema = mixed().test(
"isBigint",
new InvalidParameter("bigint").message,
(value) => typeof value === "bigint",
);
export const AddressOrEnsSchema = string().notRequired().test(
"isAddressOrEns",
new InvalidAddressOrEnsError().message,
(value) => value ? isAddress(value) || isEnsName(value) : true,
);
export const VersionTagSchema = object({
build: number().moreThan(0).required(),
release: number().moreThan(0).required(),
});
export const AbiSchema = array().notRequired().test(
"isValidAbi",
new InvalidContractAbiError().message,
// TODO: validate abi
() => true,
);
export const Uint8ArraySchema = mixed().test(
"isUint8Array",
new InvalidParameter("Uint8Array").message,
(value) => value ? value instanceof Uint8Array : true,
);
export const IpfsUriSchema = string().test(
"isIpfsUri",
new InvalidCidError().message,
(value) => value ? isIpfsUri(value) : true,
);
export const SubdomainSchema = string().test(
"isSubdomain",
new InvalidSubdomainError().message,
(value) => value ? isSubdomain(value) : true,
);

export const PaginationSchema = object({
skip: number().min(0).notRequired(),
limit: number().min(1).notRequired(),
direction: string().oneOf(["asc", "desc"]).notRequired(),
});

export const PrepareUninstallationSchema = object({
daoAddressOrEns: AddressOrEnsSchema.required(),
pluginAddress: AddressOrEnsSchema.required(),
pluginInstallationIndex: number().notRequired().min(0),
uninstallationParams: array().notRequired(),
uninstallationAbi: AbiSchema.notRequired(),
});
export const MultiTargetPermissionSchema = object({
operation: number().required().oneOf([0, 1, 2]),
permissionId: string().required(),
where: AddressOrEnsSchema.required(),
who: AddressOrEnsSchema.required(),
condition: string().notRequired(),
});

export const PrepareInstallationSchema = object({
daoAddressOrEns: AddressOrEnsSchema.required(),
pluginRepo: AddressOrEnsSchema.required(),
version: VersionTagSchema.notRequired(),
installationParams: array().notRequired(),
installationAbi: AbiSchema.notRequired(),
});

export const PluginInstallItemSchema = object({
id: AddressOrEnsSchema.required(),
data: Uint8ArraySchema.required(),
});

export const ApplyUninstallationSchema = object({
pluginAddress: AddressOrEnsSchema.required(),
pluginRepo: AddressOrEnsSchema.required(),
versionTag: VersionTagSchema.required(),
permissions: array(MultiTargetPermissionSchema).required(),
});

export const ApplyInstallationSchema = ApplyUninstallationSchema.concat(object({
helpers: array(AddressOrEnsSchema).required(),
}));
21 changes: 21 additions & 0 deletions modules/client-common/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,27 @@ export type DecodedApplyInstallationParams = ApplyInstallationParamsBase & {
helpersHash: string;
};

/* Uninstallation */
export type PrepareUninstallationParams = {
daoAddressOrEns: string;
pluginAddress: string;
pluginInstallationIndex?: number;
uninstallationParams?: any[];
uninstallationAbi?: string[];
};
export enum PrepareUninstallationSteps {
PREPARING = "preparing",
DONE = "done",
}
export type PrepareUninstallationStepValue =
| { key: PrepareUninstallationSteps.PREPARING; txHash: string }
| {
key: PrepareUninstallationSteps.DONE;
} & ApplyUninstallationParams;

export type ApplyUninstallationParams = ApplyInstallationParamsBase;
export type DecodedApplyUninstallationParams = ApplyInstallationParamsBase;

export type VersionTag = {
build: number;
release: number;
Expand Down
21 changes: 21 additions & 0 deletions modules/client-common/test/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,24 @@ export const TEST_ABI: MetadataAbiInput[] = [
],
},
];


export const TEST_ADDRESS = "0x0000000000000000000000000000000000000001";
export const TEST_INVALID_ADDRESS =
"0x000000000000000000000000000000000000000P";

export const TEST_ENS_NAME = "test.eth";
export const TEST_INVALID_ENS_NAME = "test.invalid";

export const TEST_IPFS_URI_V0 =
"ipfs://QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR";
export const TEST_IPFS_URI_V1 =
"ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi";
export const TEST_INVALID_IPFS_URI =
"ipfs://QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR-invalid";

export const TEST_HTTP_URI = "http://test.com";
export const TEST_INVALID_HTTP_URI = "http://te?st.com-invalid";

export const TEST_SUBDOMAIN = "test";
export const TEST_INVALID_SUBDOMAIN = "test.invalid";
Loading

0 comments on commit a57763b

Please sign in to comment.