def auth_redmine(username, password): redmine = Redmine('http://ticket.wise-paas.com', username=username, password=password) try: redmine.auth() return "ok" except Exception as e: return "auth failed: " + str(e)
def sync_data_from_redmine(self): params = self.env['ir.config_parameter'].sudo() if not any([params.get_param('redmine_timesheet.redmine_api_key'), params.get_param('redmine_timesheet.redmine_url')]): raise UserError(_('Please set redmine api credentials')) try: from redminelib import Redmine except ImportError: raise UserError(_('Missing python dependency, check https://python-redmine.com/')) redmine = Redmine(params.get_param('redmine_timesheet.redmine_url'), key=params.get_param('redmine_timesheet.redmine_api_key')) try: redmine.auth() except Exception as e: raise UserError(_(e)) _logger.info('Connect with Redmine') for project in list(redmine.project.all()): proj_obj = self._get_or_create_project(project) _logger.info("Project: {} - been find in odoo ".format(proj_obj.name)) for task in self._get_tasks_from_project(project): task_obj = self._get_or_create_task(task, proj_obj) _logger.info(u"Task: {} - been find in odoo ".format(task_obj.name)) for time_entry in self._get_time_entrys_from_task(task): self._get_or_create_timesheet(task_obj, time_entry, proj_obj)
def set_key(self, bot: Bot, update: Update, session: Session): tg_user = update.message.from_user user = find_user(session, tg_user.id) if user is None: update.message.reply_text(m.NOT_FOUND_USER) return tg.ConversationHandler.END try: redmine = Redmine(url=self.config.redmine_host, key=update.message.text) redmine.auth() except AuthError: update.message.reply_text(m.INVALID_REDMINE_KEY) user.redmine_user.key = '' session.add(user.redmine_user) session.commit() return tg.ConversationHandler.END user.redmine_user.key = update.message.text session.add(user.redmine_user) session.commit() update.message.reply_text(m.DONE_REDMINE_SETTINGS) update.message.reply_text(m.WELCOME_MESSAGES) return tg.ConversationHandler.END
def check_authkey(self, authkey): """Check authorization key. :param string authkey: Authorization key to check :return: True if authorization key is correct """ redmine = Redmine(url=self.url, key=authkey) try: redmine.auth() return True except AuthError: return False
def auth_user(username, password, teste=True, verify=True): url = URLHM if teste else URL fiscaliza = Redmine( url, username=username, password=password, requests={"verify": verify} ) try: fiscaliza.auth() return fiscaliza except ConnectionError: console.print( "[bold red] Sem resposta do Servidor. Verifique: Conexão com a Internet | VPN | Fiscaliza fora do ar" )
def get_all_time_entry(self, user, spent_on=None): """Get all time entry from redmine for user. :param tracktime.models.User user: :param spent_on: :rtype: list """ redmine = Redmine(url=self.url, key=user.authkey) try: time_entries = list() r_user_id = redmine.auth().id r_time_entries = redmine.time_entry.filter(user_id=r_user_id, spent_on=spent_on) for r_time_entry in r_time_entries: if 'issue' in dir(r_time_entry): time_entry = TimeEntry(id=r_time_entry.id, user=user, issue_id=r_time_entry.issue.id, spent_on=r_time_entry.spent_on, hours=r_time_entry.hours, comments=r_time_entry.comments) time_entries.append(time_entry) return time_entries except AuthError: return list()
def spent_on(self, bot, update, user_data, session): tg_message = update.callback_query.message user_data['spent_on'] = dt.datetime.strptime( update.callback_query.data, '%Y-%m-%d').date() user = find_user(session, update.effective_user.id) if user is None or user.redmine_user.empty(): tg_message.reply_text(m.NOT_FOUND_USER) return tg.ConversationHandler.END redmine = Redmine(url=self.config.redmine_host, key=user.redmine_user.key) issues = self.config.redmine_general_issue for issue in redmine.auth().issues: issues[issue.id] = issue.subject user_data['issues'] = issues buttons = [ InlineKeyboardButton(name, callback_data=str(id)) for id, name in issues.items() ] reply_markup = InlineKeyboardMarkup(build_menu(buttons, n_cols=1)) bot.edit_message_text(m.SET_ISSUE.format( self.track_task_to_str(user_data)), chat_id=tg_message.chat.id, message_id=tg_message.message_id, reply_markup=reply_markup) return SET_ISSUE
def _check_redmine_authorization(self, vals): _logger.info(self.env['ir.config_parameter'].sudo().get_param( 'redmine_timesheet.redmine_url')) try: from redminelib import Redmine except ImportError: raise UserError( _('Missing python dependency, check https://python-redmine.com/' )) redmine = Redmine(vals.get('redmine_url'), key=vals.get('redmine_api_key')) try: redmine.auth() except Exception as e: raise UserError(_(e))
class RedmineWrapper(object): redmine: Redmine = None def connect(self, user, pswd): self.redmine = Redmine("https://redmine.sparc-npo.ru", username=user, password=pswd, requests={'verify': False}) try: auth = self.redmine.auth() except AuthError: raise Exception('Invalid login or password provided') def getIssues(self, projectname, versionname): projects = [ project for project in self.redmine.project.all() if project.name == projectname ] # Все проекты с заданным именем if not projects: return None versions = [ list(project.versions.filter(name=versionname)) for project in projects ] # Все версии с заданным именем для каждого из найденных проектов versions = list( chain(*versions) ) # слияние всех найденных версий в один общий список. Если получилась не одна, значит что-то не так if len(versions) != 1: return None versionid = versions[0].id issues = [] for resource in self.redmine.issue.filter(fixed_version_id=versionid, status_id='*'): issue = ParseResource(resource) issues.append(issue) issues.sort(key=lambda issue: (issue.Result, issue.Weight), reverse=True) return issues
class RedMineManager: def __init__(self, username, password): self.username = username self.password = password self.__valid_redmine_login = None self.projects_list = None self.all_projects = None self.issues_dict = None self.redmine = Redmine(constants.REDMINE_URL, username=self.username, password=self.password) def validate_login(self): """ Validates the login credentials of the user. """ is_user_valid = None try: if self.redmine.auth(): self.__valid_redmine_login = True is_user_valid = True except Exception as error: print(error) return is_user_valid def get_projects(self): """ Gets the list of projects. :return: projects_list: A list of names of all the projects. """ if self.__valid_redmine_login: self.all_projects = self.redmine.project.all() self.projects_list = [ project.name for project in self.all_projects ] projects_list = self.projects_list return projects_list def get_project_trackers(self, project_name): """ Gets all the trackers added to the project in redmine. :param project_name: Name of the project. :return: trackers_list: List of all the trackers in the project. """ if self.__valid_redmine_login: trackers_list = [] all_projects = self.redmine.project.all() for project in all_projects: if project.name == project_name: for tracker in project.trackers: trackers_list.append(tracker.name) break return trackers_list def total_projects_count(self): """ Gets the total number of projects. :return: total_projects: A total count of all the projects. """ total_projects = str(len(self.get_projects())) return total_projects def get_issues(self): """ Gets all the issues created by the user. :return: issues_dict: A dictionary that contains issues created by the user along with some of its information. """ if self.__valid_redmine_login: self.issues_dict = {} for issue in self.redmine.issue.all(): issue_dict = { 'subject': issue.subject, 'status': str(issue.status), 'priority': str(issue.priority), 'description': issue.description } self.issues_dict[issue.id] = issue_dict issues_dict = self.issues_dict return issues_dict def total_issues_count(self): """ Gets the total number of issues created by the user. :return: total_issues: A total count of all the issues. """ if self.__valid_redmine_login: total_issues = str(len(self.get_issues())) return total_issues def total_issues_resolved_count(self): """ Gets the total number of issues whose status is resolved. :return: total_resolved: A total count of issues whose status is resolved. """ if self.__valid_redmine_login: total_resolved = 0 for issue_key in self.issues_dict: if self.issues_dict[issue_key][ 'status'] == constants.RESOLVED_STATUS: total_resolved += 1 total_resolved = str(total_resolved) return total_resolved def total_issues_pending_count(self): """ Gets the total number of issues whose status is not resolved. :return: total_pending: A total count of issues whose status is not resolved. """ if self.__valid_redmine_login: total_pending = 0 for issue_key in self.issues_dict: if self.issues_dict[issue_key][ 'status'] != constants.RESOLVED_STATUS: total_pending += 1 total_pending = str(total_pending) return total_pending def create_new_issue(self, project_name, tracker_name, subject, description, priority_id): """ Creates a new issue in redmine. :param project_name: Name of the project. :param tracker_name: Name of the tracker. :param subject: Subject of the issue. :param description: Description of the issue. :param priority_id: Priority ID for the issue. """ if self.__valid_redmine_login: for project in self.all_projects: if project.name == project_name: self.redmine.issue.create(project_id=project.id, tracker_name=tracker_name, subject=subject, description=description, priority_id=priority_id) break def clear_data_on_logout(self): """ Reassigns variables to None. """ self.projects_list = None self.issues_dict = None self.redmine = None self.__valid_redmine_login = None
class Redmine(Tracker): def __init__(self, url, token=None, login=None, password=None): if token is None and (login is None or password is None): raise AttributeError self.api = None # type: RedmineLib if token is None: self.api = RedmineLib(url, username=login.encode('utf-8'), password=password.encode('utf-8')) else: self.api = RedmineLib(url, key=token) self.auth = self.__is_auth() def __is_auth(self) -> bool: try: auth = self.api.auth() except AuthError: auth = None return auth is not None @staticmethod def as_dict(obj): return obj.__dict__.get('_decoded_attrs') def res_to_list(self, res) -> List[Any]: return [self.as_dict(item) for item in res if res is not None and item is not None] def __get_project(self, id_or_code): if self.auth: try: project = self.api.project.get(id_or_code) except ResourceNotFoundError: return None return Project(id=project.id, code=project.identifier, name=project.name) def __filter_activities(self, filter) -> Optional[List[Activity]]: if self.auth: try: activities = self.api.time_entry.filter(**filter) except ResourceNotFoundError: return None result = [] for item in activities: item = self.as_dict(item) comment = item.get('comments') or '' if comment == '': comment = None result.append( Activity(date=dt.datetime.strptime(item.get('spent_on'), '%Y-%m-%d').date(), time=item.get('hours'), id=item.get('id'), user_id=item.get('user').get('id'), task_id=item.get('issue').get('id'), category_id=item.get('activity').get('id'), project_id=item.get('project').get('id'), comment=comment)) return result ######################################### Tracker interface ######################################################## def get_tracker_type(self) -> Optional[str]: """ Возвращает тип трекера """ return 'redmine' def is_auth(self) -> bool: """ Проверяет, авторизован ли пользователь на трекере """ return self.auth def get_api_key(self) -> Optional[str]: """ Получает api_key пользователя для трекера, если трекер имеет такую возможность :return: возвращает api_key или None """ if self.auth: return self.api.auth().api_key def get_user_id(self) -> Optional[int]: """ Получает id пользователя на трекере, если он авторизован :return: возвращает user_id или None """ if self.auth: return self.api.auth().id def list_categories(self) -> Optional[List[Category]]: """ Запрашивает список категорий активностей у трекера :return: возвращает список категорий или None """ if self.auth: categories = self.api.enumeration.filter(resource='time_entry_activities') categories = self.res_to_list(categories) return [Category(id=category['id'], name=category['name'], default=category.get('is_default', False)) for category in categories] def list_projects(self) -> Optional[List[Project]]: """ Запрашивает список проектов у трекера :return: возвращает список проектов или None """ if self.auth: projects = self.api.project.all() return [Project(id=project.id, code=project.identifier, name=project.name) for project in projects] def get_project_by_id(self, project_id: int) -> Optional[Project]: """ Запрашивает у трекера проект по id :param project_id: id запрашиваемого проекта :return: возвращает Project или None """ return self.__get_project(project_id) def get_project_by_code(self, project_code: str) -> Optional[Project]: """ Запрашивает у трекера проект по коду :param project_code: code запрашиваемого проекта :return: возвращает Project или None """ return self.__get_project(project_code) def get_project_by_name(self, project_name: str) -> Optional[Project]: """ Запрашивает у трекера проект по имени :param project_name: name запрашиваемого проекта :return: возвращает Project или None """ if self.auth: for project in self.list_projects(): if project.name == project_name: return project def get_task_by_id(self, task_id: int) -> Optional[Task]: """ Запрашивает у трекера задачу по id, если задачи поддерживаются трекером :param task_id: id запрашиваемой задачи :return: возвращает Task или None """ if self.auth: try: task = self.api.issue.get(task_id) except (ResourceNotFoundError, ForbiddenError): return None return Task(id=task.id, name=task.subject, project_id=task.project.id, project_name=task.project.name, tracker_name=task.tracker.name, status=task.status.name) def list_tasks_in_project(self, project_id: int, all: bool = False) -> Optional[List[Task]]: """ Запрашивает у трекера список задач по id проекта, если задачи поддерживаются трекером :param project_id: id проекта :param all: возвращать все задачи. По-умолчанию возвращает только открытые :return: возвращает список задач или None """ if self.auth: try: if all: tasks = self.api.issue.filter(project_id=project_id, status_id='*') else: tasks = self.api.issue.filter(project_id=project_id) except ResourceNotFoundError: return None return [Task(id=task.id, name=task.subject, project_id=task.project.id, status=task.status.name) for task in tasks] def list_activities_in_date(self, date: dt.date, user_id: int = None) -> Optional[List[Activity]]: """ Запрашивает у трекера список активностей по дате :param user_id: :param date: дата :return: возвращает список активностей или None """ return self.list_activities_in_date_interval(date, date, user_id) def list_activities_in_date_interval(self, date_start: dt.date, date_end: dt.date, user_id: int = None) -> Optional[ List[Activity]]: """ Запрашивает у трекера список активностей в интервале дат :param user_id: :param date_start: начальная дата :param date_end: конечная дата :return: возвращает список активностей или None """ return self.__filter_activities({'from_date': date_start, 'to_date': date_end, 'user_id': user_id}) def list_activities_in_task(self, task_id: int) -> Optional[List[Activity]]: """ Запрашивает у трекера список активностей по id задачи, если задачи поддерживаются трекером :param task_id: id задачи :return: возвращает список активностей или None """ return self.__filter_activities({'issue_id': task_id}) def list_activities_in_project(self, project_id: int) -> Optional[List[Activity]]: """ Запрашивает у трекера список активностей по id проекта :param project_id: id проекта :return: возвращает список активностей или None """ return self.__filter_activities({'project_id': project_id}) def new_activity(self, activity: Activity) -> Optional[int]: """ Создает новую активность на трекере :param activity: активность :return: возвращает activity_id созданной активности, или None, в случае неудачи """ time_entry = self.api.time_entry.new() time_entry.issue_id = activity.task_id time_entry.spent_on = activity.date time_entry.hours = activity.time time_entry.activity_id = activity.category_id time_entry.comments = activity.comment time_entry.save() return time_entry.id ######################################### end Tracker interface #################################################### def get_all_projects(self): return self.api.project.all() def get_all_tasks(self): return self.api.issue.all() def get_api(self): return self.api