Skip to content

Commit

Permalink
change(pass-webauthn): tests
Browse files Browse the repository at this point in the history
  • Loading branch information
pandres95 committed Oct 11, 2024
1 parent d1e1f05 commit 8dedcfa
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 24 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 3 additions & 6 deletions pass-webauthn/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,25 @@ version = "0.1.0"
[dependencies]
codec.workspace = true
frame-support.workspace = true
frame-system.workspace = true
frame-support.optional = true
scale-info.workspace = true
traits-authn.workspace = true
verifier.workspace = true

[dev-dependencies]
frame-system.workspace = true
pallet-balances.workspace = true
pallet-pass.workspace = true
sp-io.workspace = true
sp-runtime.workspace = true

[features]
default = ["std", "runtime"]
runtime = []
runtime = ["frame-support"]
runtime-benchmarks = [
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-pass/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
]
std = [
"codec/std",
Expand All @@ -38,7 +37,6 @@ std = [
"pallet-pass/std",
"scale-info/std",
"sp-io/std",
"sp-runtime/std",
"traits-authn/std",
"verifier/std",
]
Expand All @@ -47,5 +45,4 @@ try-runtime = [
"frame-system/try-runtime",
"pallet-balances/try-runtime",
"pallet-pass/try-runtime",
"sp-runtime/try-runtime",
]
23 changes: 21 additions & 2 deletions pass-webauthn/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ use core::marker::PhantomData;

use frame_support::Parameter;
use traits_authn::{
AuthorityId, Challenge, DeviceChallengeResponse, DeviceId, HashedUserId, UserChallengeResponse,
AuthorityId, Challenge, Challenger, DeviceChallengeResponse, DeviceId, HashedUserId,
UserChallengeResponse,
};
use verifier::webauthn_verify;

use crate::{Attestation, Credential};
use crate::{Attestation, Credential, CxOf, Device, DeviceInfo};

impl<Cx> Attestation<Cx>
where
Expand Down Expand Up @@ -64,6 +65,24 @@ where
}
}

#[cfg(any(feature = "runtime", test))]
impl<Ch, A> From<Attestation<CxOf<Ch>>> for Device<Ch, A>
where
Ch: Challenger,
CxOf<Ch>: Parameter + Copy + 'static,
{
fn from(value: Attestation<CxOf<Ch>>) -> Self {
Device::new(DeviceInfo(value.device_id().clone()))

Check warning on line 75 in pass-webauthn/src/impls.rs

View workflow job for this annotation

GitHub Actions / clippy

using `clone` on type `[u8; 32]` which implements the `Copy` trait

warning: using `clone` on type `[u8; 32]` which implements the `Copy` trait --> pass-webauthn/src/impls.rs:75:32 | 75 | Device::new(DeviceInfo(value.device_id().clone())) | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*value.device_id()` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#clone_on_copy = note: `#[warn(clippy::clone_on_copy)]` on by default
}
}

#[cfg(any(feature = "runtime", test))]
impl AsRef<DeviceId> for DeviceInfo {
fn as_ref(&self) -> &DeviceId {
&self.0
}
}

impl<Cx> Credential<Cx>
where
Cx: Parameter,
Expand Down
22 changes: 7 additions & 15 deletions pass-webauthn/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@

use core::marker::PhantomData;

use codec::{Decode, Encode};
use frame_support::Parameter;
use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use traits_authn::{
util::{Auth, Dev},
Challenger,
Challenger, DeviceId,
};

type CxOf<Ch> = <Ch as Challenger>::Context;
Expand All @@ -20,7 +19,11 @@ mod impls;
#[cfg(any(feature = "runtime", test))]
pub type Authenticator<Ch, A> = Auth<Device<Ch, A>, Attestation<CxOf<Ch>>>;
#[cfg(any(feature = "runtime", test))]
pub type Device<Ch, A> = Dev<Vec<u8>, A, Ch, Credential<CxOf<Ch>>>;
pub type Device<Ch, A> = Dev<DeviceInfo, A, Ch, Credential<CxOf<Ch>>>;

#[cfg(any(feature = "runtime", test))]
#[derive(MaxEncodedLen, TypeInfo, Decode, Encode)]
pub struct DeviceInfo(DeviceId);

#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone)]
pub struct Attestation<Cx> {
Expand All @@ -31,17 +34,6 @@ pub struct Attestation<Cx> {
pub(crate) signature: Vec<u8>,
}

#[cfg(any(feature = "runtime", test))]
impl<Ch, A> From<Attestation<CxOf<Ch>>> for Device<Ch, A>
where
Ch: Challenger,
CxOf<Ch>: Parameter,
{
fn from(value: Attestation<CxOf<Ch>>) -> Self {
Device::new(value.public_key)
}
}

#[derive(Encode, Decode, TypeInfo, Debug, PartialEq, Eq, Clone)]
pub struct Credential<Cx> {
__phantom: PhantomData<Cx>,
Expand Down
114 changes: 114 additions & 0 deletions pass-webauthn/src/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
//! Test environment for pass webauthn.
use frame_support::{
assert_noop, assert_ok, derive_impl, parameter_types,
sp_runtime::{str_array as s, traits::Hash},
traits::ConstU64,
PalletId,
};
use frame_system::{pallet_prelude::BlockNumberFor, Config, EnsureRootWithSuccess};
use traits_authn::{util::AuthorityFromPalletId, Challenger, HashedUserId};

use crate::{Attestation, Authenticator};

#[frame_support::runtime]
pub mod runtime {
#[runtime::runtime]
#[runtime::derive(
RuntimeCall,
RuntimeEvent,
RuntimeError,
RuntimeOrigin,
RuntimeTask,
RuntimeHoldReason,
RuntimeFreezeReason
)]
pub struct Test;

#[runtime::pallet_index(0)]
pub type System = frame_system;
#[runtime::pallet_index(1)]
pub type Pass = pallet_pass;

#[runtime::pallet_index(10)]
pub type Balances = pallet_balances;
}

pub type Block = frame_system::mocking::MockBlock<Test>;
pub type AccountId = <Test as frame_system::Config>::AccountId;

#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
impl frame_system::Config for Test {
type BaseCallFilter = frame_support::traits::Everything;
type Block = Block;
type AccountData = pallet_balances::AccountData<AccountId>;
}

#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig as pallet_balances::DefaultConfig)]
impl pallet_balances::Config for Test {
type AccountStore = System;
}

parameter_types! {
pub PassPalletId: PalletId = PalletId(*b"pass/web");
pub NeverPays: Option<pallet_pass::DepositInformation<Test>> = None;
}

pub struct BlockChallenger;

impl Challenger for BlockChallenger {
type Context = BlockNumberFor<Test>;

fn generate(_: &Self::Context) -> traits_authn::Challenge {
<Test as Config>::Hashing::hash(&System::block_number().to_le_bytes()).0
}
}

impl pallet_pass::Config for Test {
type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall;
type Currency = Balances;
type Authenticator = Authenticator<BlockChallenger, AuthorityFromPalletId<PassPalletId>>;
type PalletsOrigin = OriginCaller;
type PalletId = PassPalletId;
type MaxSessionDuration = ConstU64<10>;
type RegisterOrigin = EnsureRootWithSuccess<Self::AccountId, NeverPays>;
type WeightInfo = ();
}

fn new_test_ext() -> sp_io::TestExternalities {
let mut t = sp_io::TestExternalities::default();
t.execute_with(|| {
System::set_block_number(1);
});
t
}

const USER: HashedUserId = s("the_user");

#[test]
fn registration_fails_if_attestation_is_invalid() {
new_test_ext().execute_with(|| {
// TODO: Fill with garbage data or incorrect signature (whatever works best)
assert_noop!(
Pass::register(
RuntimeOrigin::root(),
USER,
Attestation::new(b"".to_vec(), b"".to_vec(), b"".to_vec(), b"".to_vec())
),
pallet_pass::Error::<Test>::DeviceAttestationInvalid,
);
})
}

#[test]
fn registration_works_if_attestation_is_valid() {
new_test_ext().execute_with(|| {
// TODO: Fill with valid data and signature
assert_ok!(Pass::register(
RuntimeOrigin::root(),
USER,
Attestation::new(b"".to_vec(), b"".to_vec(), b"".to_vec(), b"".to_vec())
));
})
}

0 comments on commit 8dedcfa

Please sign in to comment.