sol_cerberus/instructions/
assign_role.rs1use crate::instructions::allowed::{allowed, AllowedRule};
2use crate::metadata_program;
3use crate::state::app::{App, Seed};
4use crate::state::role::*;
5use crate::state::rule::{Namespaces, Rule};
6use crate::utils::{roles::address_or_wildcard, rules::*, utc_now};
7use crate::Errors::InvalidRole;
8use anchor_lang::prelude::*;
9use anchor_spl::{metadata::MetadataAccount, token::TokenAccount};
10
11#[derive(Accounts)]
21#[instruction(assign_role_data:AssignRoleData)]
22pub struct AssignRole<'info> {
23 #[account(mut)]
24 pub signer: Signer<'info>,
25 #[account(
26 init,
27 payer = signer,
28 space = 105,
29 seeds = [assign_role_data.role.as_ref(), address_or_wildcard(&assign_role_data.address), sol_cerberus_app.id.key().as_ref()],
30 constraint = valid_rule(&assign_role_data.role, true) @ InvalidRole,
31 bump
32 )]
33 pub role: Account<'info, Role>,
34 #[account(
35 seeds = [b"app".as_ref(), sol_cerberus_app.id.key().as_ref()],
36 bump = sol_cerberus_app.bump,
37 )]
38 pub sol_cerberus_app: Box<Account<'info, App>>,
39 #[account(
40 seeds = [sol_cerberus_role.role.as_ref(), address_or_wildcard(&sol_cerberus_role.address), sol_cerberus_role.app_id.key().as_ref()],
41 bump = sol_cerberus_role.bump
42 )]
43 pub sol_cerberus_role: Option<Box<Account<'info, Role>>>,
44 #[account(
45 seeds = [sol_cerberus_rule.namespace.to_le_bytes().as_ref(), sol_cerberus_rule.role.as_ref(), sol_cerberus_rule.resource.as_ref(), sol_cerberus_rule.permission.as_ref(), sol_cerberus_rule.app_id.key().as_ref()],
46 bump = sol_cerberus_rule.bump,
47 )]
48 pub sol_cerberus_rule: Option<Box<Account<'info, Rule>>>,
49 #[account()]
50 pub sol_cerberus_token: Option<Box<Account<'info, TokenAccount>>>,
51 #[account(
52 seeds = [b"metadata", metadata_program::ID.as_ref(), sol_cerberus_metadata.mint.key().as_ref()],
53 seeds::program = metadata_program::ID,
54 bump,
55 )]
56 pub sol_cerberus_metadata: Option<Box<Account<'info, MetadataAccount>>>,
57 #[account(
58 init_if_needed,
59 payer = signer,
60 space = 9, seeds = [b"seed".as_ref(), signer.key.as_ref()],
62 bump
63 )]
64 pub sol_cerberus_seed: Option<Account<'info, Seed>>,
65 pub system_program: Program<'info, System>,
66}
67
68pub fn assign_role(ctx: Context<AssignRole>, assign_role_data: AssignRoleData) -> Result<()> {
69 allowed(
70 &ctx.accounts.signer,
71 &ctx.accounts.sol_cerberus_app,
72 &ctx.accounts.sol_cerberus_role,
73 &ctx.accounts.sol_cerberus_rule,
74 &ctx.accounts.sol_cerberus_token,
75 &ctx.accounts.sol_cerberus_metadata,
76 &mut ctx.accounts.sol_cerberus_seed,
77 &ctx.accounts.system_program,
78 AllowedRule {
79 app_id: ctx.accounts.sol_cerberus_app.id.key(),
80 namespace: Namespaces::AssignRole as u8,
81 resource: assign_role_data.address_type.to_string(),
82 permission: assign_role_data.role.clone(),
83 },
84 )?;
85
86 let role = &mut ctx.accounts.role;
87 role.bump = ctx.bumps.role;
88 role.app_id = ctx.accounts.sol_cerberus_app.id;
89 role.address = assign_role_data.address;
90 role.role = assign_role_data.role;
91 role.address_type = assign_role_data.address_type;
92 role.expires_at = assign_role_data.expires_at;
93 emit!(RolesChanged {
94 time: utc_now(),
95 app_id: ctx.accounts.sol_cerberus_app.id,
96 });
97 Ok(())
98}