Closed
Description
Motivation
- The Action, Service structure defines common behaviors that do not have REST or GraphQL dependencies. However, in the
create_user
method of the UserService, you notice that a graphql-defined behavior is being used, and you want to remove it - As
prepare_new_keypair
is common behavior, it needs to be extract as standalone utility function
Required Features
async def _post_func(conn: SAConnection, result: Result) -> Optional[Row]:
if result.rowcount == 0:
return None
created_user = result.first()
# Create a default keypair for the user.
email = action.input.email
kp_data = CreateKeyPair.prepare_new_keypair(
email,
{
"is_active": _status == UserStatus.ACTIVE,
"is_admin": user_data["role"] in [UserRole.SUPERADMIN, UserRole.ADMIN],
"resource_policy": DEFAULT_KEYPAIR_RESOURCE_POLICY_NAME,
"rate_limit": DEFAULT_KEYPAIR_RATE_LIMIT,
},
)
kp_insert_query = sa.insert(keypairs).values(
**kp_data,
user=created_user.uuid,
)
class CreateKeyPair(graphene.Mutation):
allowed_roles = (UserRole.SUPERADMIN,)
class Arguments:
user_id = graphene.String(required=True)
props = KeyPairInput(required=True)
ok = graphene.Boolean()
msg = graphene.String()
keypair = graphene.Field(lambda: KeyPair, required=False)
@classmethod
async def mutate(
cls,
root,
info: graphene.ResolveInfo,
user_id: str,
props: KeyPairInput,
) -> CreateKeyPair:
from .user import users # noqa
graph_ctx: GraphQueryContext = info.context
data = cls.prepare_new_keypair(
user_id,
{
"is_active": props.is_active,
"is_admin": props.is_admin,
"resource_policy": props.resource_policy,
"rate_limit": props.rate_limit,
# props.concurrency_limit is always ignored
},
)
insert_query = sa.insert(keypairs).values(
**data,
user=sa.select([users.c.uuid]).where(users.c.email == user_id).as_scalar(),
)
return await simple_db_mutate_returning_item(cls, graph_ctx, insert_query, item_cls=KeyPair)
@classmethod
def prepare_new_keypair(cls, user_email: str, props: KeyPairInputTD) -> Dict[str, Any]:
ak, sk = generate_keypair()
pubkey, privkey = generate_ssh_keypair()
data = {
"user_id": user_email,
"access_key": ak,
"secret_key": sk,
"is_active": props["is_active"],
"is_admin": props["is_admin"],
"resource_policy": props["resource_policy"],
"rate_limit": props["rate_limit"],
"num_queries": 0,
"ssh_public_key": pubkey,
"ssh_private_key": privkey,
}
return data
Impact
- Organize code better fit the original intent of Action / Service structure
Testing Scenarios
- Verify that keypairs are created correctly when a user is created
Metadata
Metadata
Assignees
Labels
No labels