|
| 1 | +"""Creates a user """ |
| 2 | +# :license: MIT, see LICENSE for more details. |
| 3 | + |
| 4 | +import json |
| 5 | +import string |
| 6 | +import sys |
| 7 | + |
| 8 | +import click |
| 9 | + |
| 10 | +import SoftLayer |
| 11 | +from SoftLayer.CLI import environment |
| 12 | +from SoftLayer.CLI import exceptions |
| 13 | +from SoftLayer.CLI import formatting |
| 14 | +from SoftLayer.CLI import helpers |
| 15 | + |
| 16 | + |
| 17 | +@click.command() |
| 18 | +@click.argument('username') |
| 19 | +@click.option('--email', '-e', required=True, |
| 20 | + help="Email address for this user. Required for creation.") |
| 21 | +@click.option('--password', '-p', default=None, show_default=True, |
| 22 | + help="Password to set for this user. If no password is provided, user will be sent an email " |
| 23 | + "to generate one, which expires in 24 hours. '-p generate' will create a password for you " |
| 24 | + "(Requires Python 3.6+). Passwords require 8+ characters, upper and lowercase, a number " |
| 25 | + "and a symbol.") |
| 26 | +@click.option('--from-user', '-u', default=None, |
| 27 | + help="Base user to use as a template for creating this user. " |
| 28 | + "Will default to the user running this command. Information provided in --template " |
| 29 | + "supersedes this template.") |
| 30 | +@click.option('--template', '-t', default=None, |
| 31 | + help="A json string describing https://softlayer.github.io/reference/datatypes/SoftLayer_User_Customer/") |
| 32 | +@click.option('--api-key', '-a', default=False, is_flag=True, help="Create an API key for this user.") |
| 33 | +@environment.pass_env |
| 34 | +def cli(env, username, email, password, from_user, template, api_key): |
| 35 | + """Creates a user Users. |
| 36 | +
|
| 37 | + :Example: slcli user create my@email.com -e my@email.com -p generate -a |
| 38 | + -t '{"firstName": "Test", "lastName": "Testerson"}' |
| 39 | +
|
| 40 | + Remember to set the permissions and access for this new user. |
| 41 | + """ |
| 42 | + |
| 43 | + mgr = SoftLayer.UserManager(env.client) |
| 44 | + user_mask = ("mask[id, firstName, lastName, email, companyName, address1, city, country, postalCode, " |
| 45 | + "state, userStatusId, timezoneId]") |
| 46 | + from_user_id = None |
| 47 | + if from_user is None: |
| 48 | + user_template = mgr.get_current_user(objectmask=user_mask) |
| 49 | + from_user_id = user_template['id'] |
| 50 | + else: |
| 51 | + from_user_id = helpers.resolve_id(mgr.resolve_ids, from_user, 'username') |
| 52 | + user_template = mgr.get_user(from_user_id, objectmask=user_mask) |
| 53 | + # If we send the ID back to the API, an exception will be thrown |
| 54 | + del user_template['id'] |
| 55 | + |
| 56 | + if template is not None: |
| 57 | + try: |
| 58 | + template_object = json.loads(template) |
| 59 | + for key in template_object: |
| 60 | + user_template[key] = template_object[key] |
| 61 | + except ValueError as ex: |
| 62 | + raise exceptions.ArgumentError("Unable to parse --template. %s" % ex) |
| 63 | + |
| 64 | + user_template['username'] = username |
| 65 | + if password == 'generate': |
| 66 | + password = generate_password() |
| 67 | + |
| 68 | + user_template['email'] = email |
| 69 | + |
| 70 | + if not env.skip_confirmations: |
| 71 | + table = formatting.KeyValueTable(['name', 'value']) |
| 72 | + for key in user_template: |
| 73 | + table.add_row([key, user_template[key]]) |
| 74 | + table.add_row(['password', password]) |
| 75 | + click.secho("You are about to create the following user...", fg='green') |
| 76 | + env.fout(table) |
| 77 | + if not formatting.confirm("Do you wish to continue?"): |
| 78 | + raise exceptions.CLIAbort("Canceling creation!") |
| 79 | + |
| 80 | + result = mgr.create_user(user_template, password) |
| 81 | + new_api_key = None |
| 82 | + if api_key: |
| 83 | + click.secho("Adding API key...", fg='green') |
| 84 | + new_api_key = mgr.add_api_authentication_key(result['id']) |
| 85 | + |
| 86 | + table = formatting.Table(['Username', 'Email', 'Password', 'API Key']) |
| 87 | + table.add_row([result['username'], result['email'], password, new_api_key]) |
| 88 | + env.fout(table) |
| 89 | + |
| 90 | + |
| 91 | +def generate_password(): |
| 92 | + """Returns a 23 character random string, with 3 special characters at the end""" |
| 93 | + if sys.version_info > (3, 6): |
| 94 | + import secrets # pylint: disable=import-error |
| 95 | + alphabet = string.ascii_letters + string.digits |
| 96 | + password = ''.join(secrets.choice(alphabet) for i in range(20)) |
| 97 | + special = ''.join(secrets.choice(string.punctuation) for i in range(3)) |
| 98 | + return password + special |
| 99 | + else: |
| 100 | + raise ImportError("Generating passwords require python 3.6 or higher") |
0 commit comments