Ejemplo n.º 1
0
    def __init__(self, project_name, task_name):
        self.kb = Kanboard(kb_endpoint, kb_user, kb_apikey, "X-API-Auth")
        self.project_name = project_name
        self.task = None
        self.columns = None

        # This pulls in the Kanboard project ("Pentesting" as of yet)
        self.kbb_project = self.kb.get_project_by_name(name=self.project_name)
        if not self.kbb_project:
            error(
                "Could not find the *%s* project in Kanboard. Verify endpoint."
                % self.project_name)
            exit(-1)

        # This pulls in the task that will be manipulated
        tasks = self.kb.search_tasks(project_id=self.kbb_project["id"],
                                     query="title:%s" % task_name)
        if len(tasks) == 0:
            error("Could not find kanboard task with the title: %s" %
                  task_name)
            exit(-1)
        for task in tasks:
            if task_name == task["title"]:
                self.task = task
                break
        if not self.task:
            error(
                "Similar kanboard tasks for *%s* have been found, but no exact match. Check spelling."
                % task_name)
            exit(-1)

        self.description = task["description"].split("\r\n")
Ejemplo n.º 2
0
    def connect(self):
        self.gl = Gitlab(self.gitlab['endpoint'],
                         self.gitlab['token'],
                         ssl_verify=False)
        self.gl.auth()

        self.kb = Kanboard(self.kanboard['endpoint'], self.kanboard['user'],
                           self.kanboard['token'])
Ejemplo n.º 3
0
def get_tasks(options):
    """
    Return a list of tasks from the specified kanboard
    """
    tasks = None
    print(options)
    kanboard = Kanboard(options['host'] + "/jsonrpc.php",
                        username=options['username'],
                        password=options['password'],
                        http_username=options['http_username'],
                        http_password=options['http_password'],
                        proxies=options['proxy'],
                        verify=(not options['no_ssl_verify']),
                        auth_header=options['auth_header'])
    try:
        tasks = kanboard.get_all_tasks(project_id=options['tasks'])
    except requests.exceptions.RequestException as exception:
        logging.error('Could not retrieve tasks: %s', exception)
        sys.exit(-1)
    except requests.packages.urllib3.exceptions.LocationParseError as exception:
        logging.error('Could not parse address: %s', exception)
    return tasks
Ejemplo n.º 4
0
class KanboardAdapter():
    def __init__(self, project_name, task_name):
        self.kb = Kanboard(kb_endpoint, kb_user, kb_apikey, "X-API-Auth")
        self.project_name = project_name
        self.task = None
        self.columns = None

        # This pulls in the Kanboard project ("Pentesting" as of yet)
        self.kbb_project = self.kb.get_project_by_name(name=self.project_name)
        if not self.kbb_project:
            error(
                "Could not find the *%s* project in Kanboard. Verify endpoint."
                % self.project_name)
            exit(-1)

        # This pulls in the task that will be manipulated
        tasks = self.kb.search_tasks(project_id=self.kbb_project["id"],
                                     query="title:%s" % task_name)
        if len(tasks) == 0:
            error("Could not find kanboard task with the title: %s" %
                  task_name)
            exit(-1)
        for task in tasks:
            if task_name == task["title"]:
                self.task = task
                break
        if not self.task:
            error(
                "Similar kanboard tasks for *%s* have been found, but no exact match. Check spelling."
                % task_name)
            exit(-1)

        self.description = task["description"].split("\r\n")
        # At this point the kbb project, the task and the description are loaded

    def get_columns(self):
        columns = self.kb.get_columns(project_id=self.kbb_project["id"])

        self.columns = dict()
        for column in columns:
            self.columns[int(column["id"])] = Column(int(column["id"]),
                                                     int(column["position"]),
                                                     column["title"])

        return self.columns

    def get_column(self):
        if not self.columns:
            self.get_columns()

        column_id = int(
            self.task["column_id"]
        )  # Make sure this is cast to int, otherwise comparison might go wrong

        for id in self.columns:
            if id == column_id:
                return self.columns[id]

        error("Could not determine the current column of the project")

    def update_column(self, column):
        result = self.kb.move_task_position(project_id=self.kbb_project["id"],
                                            task_id=self.task["id"],
                                            column_id=column.id,
                                            position=1)
        if not result:
            error("Unable to update column")

    def save_project_description(self):
        # Format into string
        desc = "\r\n".join(self.description)

        result = self.kb.update_task(id=self.task["id"], description=desc)
        if not result:
            error("Unable to update checklist")

    def update_project_description(self, linenr, content):
        self.description[linenr] = content

    def get_checklist_of_column(self, column):
        heading = "### Checklist %s" % column.title

        record = False
        found = False
        index = 1
        checklist = dict()

        # Loop through each line in the description
        for line in self.description:
            # Did we find the heading we're looking for? Start recording all subsequent lines
            if line.find(heading) is not -1:
                found = True
                record = True
                continue

            # Found a blank line? We're done. Stop recording
            if len(line.strip()) == 0:
                record = False

            # Add line to the checklist and update the index
            if record:
                checklist[index] = self.description.index(
                    line
                ), line  # Tuple that stores the index to the line in the description + the line itself
                index += 1

        if found is False:
            if checklist_template_url:
                error(
                    "Could not find the checklist for *%s* in kanboard task *%s*. Verify in kanboard if the task description contains the pentest checklist, which can be found here: %s"
                    %
                    (column.title, self.task["title"], checklist_template_url))
            else:
                error(
                    "Could not find the checklist for column: *%s* in kanboard task *%s*"
                    % (column.title, self.task["title"]))
            exit(-1)

        return checklist

    def save_checklist_backup(self):
        # Save description in temp dir before changing
        _, filename = tempfile.mkstemp(prefix="checklist_%s_" %
                                       self.task["title"])

        f = open(filename, "w")
        f.write("\n".join(self.description))
        f.close()
Ejemplo n.º 5
0
 def auth(self):
     return Kanboard(self.url, 'jsonrpc', self.token)
Ejemplo n.º 6
0
 def __init__(self, url: str, user: str, token: str):
     self.kb = Kanboard(url, user, token)
Ejemplo n.º 7
0
class KanboardLibrary:

    def __init__(self, url: str, user: str, token: str):
        self.kb = Kanboard(url, user, token)

    def get_version(self) -> str:
        return self.kb.execute("getVersion")

    def get_prioritys(self) -> list:
        pass

    def find_task_date_due(self, tasks: list, date_due: str) -> Task:
        for task in tasks:
            if task.date_due == date_due:
                return task
        return None

    def get_summary_tasks(self, tasks: list) -> str:
        table_list = list()
        headers = ['Project name', 'Title', 'Priority', 'Status', 'Assignee', 'Due date']
        table_list.append(headers)

        for task in tasks:
            data = task.get_summary()
            table_list.append(data)

        table = AsciiTable(table_list)
        return table.table

    def get_my_dashboard(self, printable: bool =True) -> Task:
        my_dashboard = self.kb.execute('getMyDashboard')

        tasks = list()
        for project in my_dashboard:
            task = Task(project['project_name'], project['title'], project['priority'], project['column_name'],
                        project['assignee_username'], project['date_due'])
            tasks.append(task)

        if printable:
            table = self.get_summary_tasks(tasks)
            print(table)

        return tasks

    def get_overdue_tasks(self, printable: bool =True) -> Task:
        overdue_tasks = self.kb.execute('getMyOverdueTasks')
        my_dashboard = self.get_my_dashboard(printable=False)

        tasks = list()
        for overdue_task in overdue_tasks:

            t = self.find_task_date_due(my_dashboard, overdue_task['date_due'])

            task = Task(overdue_task['project_name'], overdue_task['title'], t.priority,
                        t.column_name, overdue_task['assignee_username'], overdue_task['date_due'])
            tasks.append(task)

        if printable:
            table = self.get_summary_tasks(tasks)
            print(table)

        return tasks

    def get_project_list(self, printable=True) -> Project:
        # Get dict of projects
        projects = self.kb.execute('getMyProjectsList')

        if printable:
            table_list = list()
            headers = ['Project id', 'Project name', 'Boards']
            table_list.append(headers)

            for id in projects:
                boards = self.kb.execute('getBoard', project_id=id)
                boards_list = list()
                for item in boards:
                    boards_list.append(item['name'])

                data = [id, projects[id], ','.join(boards_list)]
                table_list.append(data)

            table = AsciiTable(table_list)
            print(table.table)

        return projects

    def get_project_id(self, project_name: str, printable=True) -> int:

        # Get dict of projects
        projects = self.get_project_list(printable=False)


        for id in projects:
            if projects[id] == project_name:
                return id

        raise KanboardException('Project not found')

    def _get_board(self, project_name: str, board_name: str) -> dict:
        project_id = self.get_project_id(project_name, printable=False)
        boards = self.kb.execute('getBoard', project_id=project_id)
        for board in boards:
            if board['name'] == board_name:
                return board

        raise KanboardException('Project or board does not exist')

    def get_board_stats(self, project_name: str, board_name: str) -> Task:

        board_data = self._get_board(project_name, board_name)

        board = Board(project_name, board_name)

        for column in board.columns:
            tasks = create_tasks_from_dict(column.tasks)
            board.add_column(column['title'], tasks)


        # tasks = list()
        # for project in my_dashboard:
        #     task = Task(project['project_name'], project['title'], project['priority'], project['column_name'],
        #                 project['assignee_username'], project['date_due'])
        #     tasks.append(task)
        #
        # if printable:
        #     table = self.get_summary_tasks(tasks)
        #     print(table)
        #
        # return tasks

        pass
Ejemplo n.º 8
0

#####################################

reload_json()

updater = Updater(token=bot_token)
dispatcher = updater.dispatcher

logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    level=logging.INFO)

#connect to kanboard
try:
    kb = Kanboard(kb_url, kb_user, kb_pw)
except:
    print(str(lang["error"]["load_bot"]))


#####################################
def is_granted(cur_id, cur_list):
    for e in range(0, len(cur_list)):
        if int(cur_id) == int(cur_list[e]):
            return True
    return False


def has_permission(bot, update):
    access = False
    cur_id = update.message.chat_id
Ejemplo n.º 9
0
from slackclient import SlackClient
from kanboard import Kanboard
import time
import os
import sys

slacktoken = os.environ['SLACKTOKEN']
kbtoken = os.environ['KBTOKEN']
kburl = os.environ['KBURL']

slack_client = SlackClient(slacktoken)
kb = Kanboard(kburl, "jsonrpc", kbtoken)

def opentask(description, projectname, channel):
    try:
        project = kb.getProjectByName(name=projectname)
        project_id = project.get('id')
        task_id = kb.create_task(project_id=project_id, title=description)
        message =  "Task Opened"
        sendmessage(channel, message)
    except:
        message = "Unknow Project"
        sendmessage(channel, message)

def sendmessage(channel, message):
    slack_client.api_call(
        'chat.postMessage',
        channel=channel,
        text=message,
        as_user='******'
        )
Ejemplo n.º 10
0
def cli(ctx, api_url, api_user, api_token, project_owner):
    """Record project info from JSON file on Kanboard."""
    project = parser_json(ctx.json_file)

    headers = {
        'User-Agent':
        'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.3'
    }

    kb = Kanboard(api_url, api_user, api_token)

    # Validating url, username and api_token provided.
    user = None
    if api_user == 'jsonrpc':
        if project_owner is None:
            print(u'You must inform the Project Owner.')
            sys.exit()
        try:
            user = kb.get_user_by_name(username=project_owner)
            if user is not None:
                print(u'User {} - {} successfully connected.'.format(
                    user['username'], user['name']))
                print_line()
            else:
                raise InvalidUsername
        except InvalidUsername:
            print(
                u'Failed to get username: {}\nWith API user: {}\nAnd API token: \"{}\"\nOn address: {}.'
                .format(project_owner, api_user, api_token, api_url))
            sys.exit()
        except Exception as e:
            print(repr(e))
            sys.exit()
    else:
        try:
            user = kb.get_me()
            print(u'User {} - {} successfully connected.'.format(
                user['username'], user['name']))
            print_line()
        except Exception as e:
            print(repr(e))
            print(
                u'Failed to get user: {}\nWith api token: \"{}\"\nOn address: {}.'
                .format(api_user, api_token, api_url))
            sys.exit()

    # Creating project
    project_id = False
    while project_id is False:
        try:
            project_id = kb.create_project(owner_id=user['id'],
                                           name=project.name)
            print(u'Project {} successfully created.'.format(project_id))
            print(u'Project name: {}.'.format(project.name))
            print_line()
        except Exception as e:
            print(repr(e))
            print(u'Failed on Project creation. Trying again.')

    # Adding user to project when using the jsonrpc API user
    if api_user == 'jsonrpc':
        user_added = False
        while user_added is False:
            user_added = kb.add_project_user(project_id=project_id,
                                             user_id=user['id'],
                                             role='project-manager')
            print(u'User {} successfully added to Project {}.'.format(
                user['username'], project_id))
            print_line()

    # Erasing default columns
    all_columns = False
    while all_columns is False:
        try:
            all_columns = kb.get_columns(project_id=project_id)
        except Exception as e:
            print(repr(e))
            print(u'Failed to get Projects columns. Trying again.')
    for c in all_columns:
        erased = False
        while erased is False:
            try:
                erased = kb.remove_column(column_id=c['id'])
                print(u'Default Column erased.')
            except Exception as e:
                print(repr(e))
                print(u'Failed to erase default Column. Trying again.')
    print_line()

    # Creating Columns
    for column in project.columns:
        column_id = False
        while column_id is False:
            try:
                column_id = kb.add_column(project_id=project_id,
                                          title=column.name)
                print(u'Column {} successfully created.'.format(column_id))
                print(u'Column name: {}.'.format(column.name))
            except Exception as e:
                print(repr(e))
                print(u'Failed on Column creation. Trying again.')

        # Creating Tasks
        for task in column.tasks:
            task_id = False
            while task_id is False:
                try:
                    task_id = kb.create_task(title=task.name,
                                             project_id=project_id,
                                             column_id=column_id,
                                             date_due=task.date_due,
                                             description=task.desc)
                    print(u'Task {} successfully created.'.format(task_id))
                except Exception as e:
                    print(repr(e))
                    print(u'Failed on Task creation. Trying again.')

            # Creating Subtask
            for subtask in task.subtasks:
                subtask_id = False
                while subtask_id is False:
                    try:
                        subtask_id = kb.create_subtask(task_id=task_id,
                                                       title=subtask.content,
                                                       status=subtask.status)
                        print(u'Subtask {} successfully created.'.format(
                            subtask_id))
                    except Exception as e:
                        print(repr(e))
                        print(u'Failed on Subtask creation. Trying again.')

            # Creating Comments
            for comment in task.comments:
                comment_id = False
                while comment_id is False:
                    try:
                        comment_id = kb.create_comment(task_id=task_id,
                                                       content=comment.content,
                                                       user_id=user['id'])
                        print(u'Comment {} successfully created.'.format(
                            comment_id))
                    except Exception as e:
                        print(repr(e))
                        print(u'Failed on Comment creation. Trying again.')

            # Creating Attachments
            for attachment in task.attachments:
                attachment_id = False
                while attachment_id is False:
                    try:
                        req = urllib.request.Request(url=attachment.url,
                                                     headers=headers)
                        filedata = base64.b64encode(
                            urllib.request.urlopen(req).read()).decode('ascii')
                        attachment_id = kb.create_task_file(
                            project_id=project_id,
                            task_id=task_id,
                            filename=attachment.filename,
                            blob=filedata)
                        print(u'Attachment {} successfully created.'.format(
                            attachment_id))
                    except Exception as e:
                        print(repr(e))
                        print(u'Failed on Attachment creation. Trying again.')

        print_line()

    print(u'Project Imported successfully.')
Ejemplo n.º 11
0
class GitlabImporter(object):
    def __init__(self, label_to_columns):
        self.label_to_columns = label_to_columns
        self.findlabel = re.compile(r'~([0-9]+)')

        # TODO: It should be optional
        requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

    def setup_gitlab(self, endpoint, token):
        self.gitlab = {
            'endpoint': endpoint,
            'token': token,
        }

    def setup_kanboard(self, endpoint, user, token):
        self.kanboard = {
            'endpoint': endpoint,
            'user': user,
            'token': token,
        }

    def connect(self):
        self.gl = Gitlab(self.gitlab['endpoint'],
                         self.gitlab['token'],
                         ssl_verify=False)
        self.gl.auth()

        self.kb = Kanboard(self.kanboard['endpoint'], self.kanboard['user'],
                           self.kanboard['token'])

    def migrate(self, namespace, project):
        _groups = [
            g for g in self.gl.groups.search(namespace) if g.name == namespace
        ]
        if not _groups:
            print(_('Error: namespace {} not found !').format(namespace))
            return False
        group = _groups[0]

        _projects = [
            p for p in group.projects.list(search=project) if p.name == project
        ]
        if not _projects:
            print(
                _('Error: project {} not found in namespace {} !').format(
                    project, namespace))
            return False

        origin = _projects[0]

        count = 0
        self.target = self.kb.createProject(
            name='{}/{}'.format(namespace, project))
        print(
            _('Project {}/{} created, id: {} !').format(
                namespace, project, self.target))
        self.project_users = self.kb.getProjectUsers(project_id=self.target)
        self.columns = self.kb.getColumns(project_id=self.target)
        self.users = self.kb.getAllUsers()
        self.labels = origin.labels.list(all=True)
        for issue in reversed(origin.issues.list(all=True)):
            creator = self.get_user_id(issue.author.username)
            owner = None
            if issue.assignee:
                owner = self.get_user_id(issue.assignee.username)
            params = {
                'title': issue.title,
                'project_id': self.target,
                'description': issue.description,
                'reference': '#{}'.format(issue.iid),
                'tags': issue.labels,
                'date_due': issue.due_date,
            }

            if creator:
                params['creator_id'] = self.check_member(creator)

            if owner:
                params['owner_id'] = self.check_member(owner)

            for label, column in self.label_to_columns.items():
                if label in issue.labels:
                    params['column_id'] = self.get_column(column)
                    params['tags'].remove(label)

            if (issue.state == 'closed'):
                params['column_id'] = self.get_column(_('Done'))

            if not params['tags']:
                del params['tags']

            task = self.kb.createTask(**params)
            if task:
                for comment in issue.notes.list(all=True):
                    body = comment.body
                    if 'label' in body:
                        for l in self.findlabel.findall(body):
                            body = body.replace('~{}'.format(l),
                                                self.get_label_by_id(l))

                    commenter_id = self.get_user_id(
                        comment.author.username) or self.users[0]['id']
                    self.kb.createComment(
                        task_id=task,
                        user_id=commenter_id,
                        content=body,
                    )

                if (issue.state == 'closed' and task):
                    self.kb.closeTask(task_id=task)

                count += 1
                print(
                    _('... issue {} migrated to task {} {}').format(
                        issue.iid, task,
                        _('(closed)') if issue.state == 'closed' else ''))
            else:
                print(_('Oops: problem to import {}').format(issue.iid))

        print(_('{} issue(s) migrated !').format(count))
        return True

    def check_member(self, member):
        if str(member) not in self.project_users:
            self.kb.addProjectUser(project_id=self.target, user_id=member)
            self.project_users = self.kb.getProjectUsers(
                project_id=self.target)
        return member

    def get_user_id(self, username):
        found = [u['id'] for u in self.users if u['username'] == username]
        if found:
            return found[0]

    def get_column(self, column):
        for c in self.columns:
            if c['title'] == column:
                return c['id']

    def get_label_by_id(self, label):
        # Some old versions of gitlab don't send id :(
        found = [l.name for l in self.labels if l.id == int(label)]
        return found[0] if found else '~{}'.format(label)
Ejemplo n.º 12
0
import configparser
import datetime

from kanboard import Kanboard

import json2kanboard

# Import configuration
config = configparser.ConfigParser()
config.read("demo.example.conf")

# Create Kanboard API instance
kanboard_instance = Kanboard(
    config.get("kanboard","url"), 
    config.get("kanboard","user"), 
    config.get("kanboard","password") 
)

# Map roles in the JSON file to task owners
roles = {
  'ROLE_MANAGER': 'user_b'
  }

# Create Kanboard project
json2kanboard.create_project(
  "onboarding_project.demo.json",
  kanboard_instance,
  project_title = "TEST_PROJECT",
  project_identifier = "TEST_PROJECT_ID",
  due_date = datetime.date(2020, 1, 1),