Git Product home page Git Product logo

slacktivate's Introduction

Slacktivate

pytest codecov Documentation Status Downloads Stargazers

Slacktivate is a Python library and Command-Line Interface to assist in the provisioning and management of a Slack workspace, using both the Slack API and the Slack SCIM API:

  • Write a YAML specifications to describe your users, channels and groups, then have Slacktivate set up your workspace with no manual intervention.

  • Use the self-documented Slacktivate REPL to immediately do batch operations on your Slack workspace and build new powerful macros.

  • Robust, Pythonic wrapper to the Slack API and Slack SCIM API clients, able to abstract some of the quirks of the API—as well as able to handle typical error management (such as rate limiting) transparently.

  • Find everything you need to be a Slack power user in one place, rather than spread to a microcosm of evolving documentations.

Installation

The package is available on PyPI as slacktivate and so is available the usual way, i.e., pip install slacktivate; in addition to the Python package, this should also install a CLI binary that is runnable, called slacktivate:

$ slacktivate --help
Usage: slacktivate [OPTIONS] COMMAND [ARGS]...

Options:
  --token $SLACK_TOKEN  Slack API token (requires being an owner or admin).
  --spec SPEC           Provide the specification for the Slack workspace.
  -y, --dry-run         Do not actually perform the action.
  --version             Show the version and exit.
  --help                Show this message and exit.

Commands:
  list      Lists any type of object defined in the provided specification...
  repl      A Python REPL with the Slacktivate package, and Slack clients...
  users     Sub-command for operations on Slack users (e.g.: activate,...
  validate  Validate the configuration file SPEC

Specification Example

The following is an example of specification for a workspace, with the user information (name, emails, perhaps additional profile information) stored here in external CSV files:

vars:
  "TERM": "2020-Q4"

users:

  - file: "input/{{ vars.TERM }}_managers*.csv"
    sort: "newest"
    type: "csv"
    key: "{{ email }}"
    fields:
      "type": ["manager", "employee"]

      # Slack normal fields
      "givenName": "{{ first }}"
      "familyName": "{{ last }}"
      "userName": "{{ email.split('@')[0] }}"

  - file: "input/{{ vars.TERM }}_associates*.csv"
    sort: "newest"
    type: "csv"
    key: "{{ email }}"
    fields:
      "type": ["employee"]

      # Slack normal fields
      "givenName": "{{ first }}"
      "familyName": "{{ last }}"
      "userName": "{{ email.split('@')[0] }}"

settings:
  slack_token: "<slack-token>"
  workspace: "https://princetoncsgrad.slack.com/"
  keep_customized_photos: true
  keep_customized_name: true
  extend_group_memberships: false
  extend_channel_memberships: false
  alternate_emails: "./output/alternate-emails.txt"

groups:
  - name: "managers"
    filter: "$.where('manager' in $.type)"

  - name: "employees"
    filter: "$.where('employee' in $.type)"

channels:
  - name: "managers-only"
    private: true
    groups: ["manager"]

  - name: "announcements"
    permissions: "admin"

  - name: "water-cooler"
    groups: ["manager", "employee"]

Introduction

Slack is a wonderful platform for chat, with an extensive API that allows for many powerful integrations. But the Slack client currently (in its most frequently available interface) does not provide any support for batch operations.

Slacktivate is a powerful tool that allows you to specify the users, group memberships and channels in a YAML specification file, and to have the tool automatically synchronize this specification with the Slack workspace.

Below is some context to explain why I created this tool.

Batch managing users in channels

As an example:

Slack modal to add users to a channel as of October 2020

and when you are managing a Slack workspace with hundreds of users, this can become a bottleneck of operations very quickly. Slack is actively trying to address this point, but so far, is not really making a difference---the channel manager that was recently introduced still only provides the same modal to add users, and no additional options to remove users.

This problem exists throughout Slack. Beyond the membership of channels, this issue exists also with the membership of the workspace, of groups, and so on.

Part of the issue is that Slack Enterprise Grid product relies on a company's existing directory solution to address these needs; but this is of no use to the many teams that are finding success with a lower tier of the service.

The solution: Automating the process

Prerequisites: Having Owner Access and Getting an API Token

In order to use the SCIM API, you need to be an owner of the workspace, and obtain an API token with admin scope.

As explained in the official Slack SCIM API documentation, the easiest way to obtain a valid token for the purposes of SCIM provisioning is as follows:

  1. As a Workspace/Organization Owner, create a new app for your workspace (see here for the documentation).
  2. Add the admin OAuth scope to the "User Token Scopes" section.
  3. Install the app to your workspace (see here for the documentation).
  4. Use the generated token available in the "OAuth & Permissions" tab (if you are provided with multiple tokens, use the "OAuth Access Token" not the "Bot User OAuth Access Token").

Note that you can easily reinstall your app with different permissions if it turns out you did not select all the necessary permissions.

License

This project is licensed under the LGPLv3 license, with the understanding that importing a Python modular is similar in spirit to dynamically linking against it.

  • You can use the library/CLI slacktivate in any project, for any purpose, as long as you provide some acknowledgement to this original project for use of the library (for open source software, just explicitly including slacktivate in the dependency such as a pyproject.toml or Pipfile is acknowledgement enough for me!).

  • If you make improvements to slacktivate, you are required to make those changes publicly available.

This license is compatible with the license of all the dependencies as documented in this project's own pyproject.toml.

slacktivate's People

Contributors

jlumbroso avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

slacktivate's Issues

Error message rather than crash when `SLACK_TOKEN` is missing

When SLACK_TOKEN is not configured, the crash is brutal:

$ pipenv run slacktivate --spec ./configuration.yaml users activate --dry-run
Traceback (most recent call last):
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/bin/slacktivate", line 8, in <module>
    sys.exit(main())
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/slacktivate/cli/__main__.py", line 220, in main
    return sys.exit(cli())
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/click/core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/click/core.py", line 782, in main
    rv = self.invoke(ctx)
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/click/core.py", line 1259, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/click/core.py", line 1259, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/click/core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/click/decorators.py", line 21, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/slacktivate/cli/commands/users.py", line 123, in users_activate
    _prep_ctx(ctx=ctx, spec=spec, dry_run=dry_run)
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/slacktivate/cli/commands/users.py", line 109, in _prep_ctx
    ctx.obj.login()
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/slacktivate/cli/helpers.py", line 201, in login
    os.environ["SLACK_TOKEN"] = self._slack_token_last_used
  File "/Users/jlumbroso/.asdf/installs/python/3.10.5/lib/python3.10/os.py", line 684, in __setitem__
    value = self.encodevalue(value)
  File "/Users/jlumbroso/.asdf/installs/python/3.10.5/lib/python3.10/os.py", line 756, in encode
    raise TypeError("str expected, not %s" % type(value).__name__)
TypeError: str expected, not NoneType

Error message rather than crash when not enough permission to deactive user

(base) princeton-cs-grad-slack (master*) » pipenv run slacktivate --spec ./configuration.yaml users deactivate
Traceback (most recent call last):
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/bin/slacktivate", line 8, in <module>
    sys.exit(main())
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/slacktivate/cli/__main__.py", line 220, in main
    return sys.exit(cli())
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/click/core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/click/core.py", line 782, in main
    rv = self.invoke(ctx)
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/click/core.py", line 1259, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/click/core.py", line 1259, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/click/core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/click/decorators.py", line 21, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/slacktivate/cli/commands/users.py", line 158, in users_deactivate
    ) = slacktivate.macros.provision.users_deactivate(
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/slacktivate/macros/provision.py", line 436, in users_deactivate
    if slacktivate.slack.methods.user_deactivate(user):
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/slacktivate/slack/methods.py", line 147, in user_deactivate
    return user_set_active(user=user, active=False)
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/slacktivate/slack/methods.py", line 115, in user_set_active
    user = user_patch(
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/backoff/_sync.py", line 94, in retry
    ret = target(*args, **kwargs)
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/slacktivate/slack/methods.py", line 90, in user_patch
    result = scim.patch_user(
  File "/Users/jlumbroso/.local/share/virtualenvs/princeton-cs-grad-slack-TURfUYtK/lib/python3.10/site-packages/slack_scim/v1/client.py", line 112, in patch_user
    raise SCIMApiError.from_response(resp)
slack_scim.v1.errors.SCIMApiError: {'status': 403, 'headers': <http.client.HTTPMessage object at 0x104c2a3e0>, 'errors': {'description': 'cannot_disable_primary_owner (user=U015S2K884B)', 'code': 403}}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.