def update_last_action(db_user: User) -> bool: """ Updates the last action field of the user-row in database. Returns boolean if the users session is older than one hour or True, when she wants to keep the login :param db_user: User in refactored fns, else nickname :return: Boolean """ if not db_user or db_user.nickname == nick_of_anonymous_user: return False timeout_in_sec = 60 * 60 * 24 * 7 # check difference of diff_action = get_now() - db_user.last_action diff_login = get_now() - db_user.last_login diff_action = diff_action.seconds + diff_action.days * 24 * 60 * 60 diff_login = diff_login.seconds + diff_login.days * 24 * 60 * 60 diff = diff_action if diff_action < diff_login else diff_login should_log_out = diff > timeout_in_sec and not db_user.settings.keep_logged_in db_user.update_last_action() transaction.commit() return should_log_out
def __check_in_local_known_user(db_user: User, password: str, _tn) -> dict: """ Tries to check in a local known user. :param db_user: current instance of User :param password: password of the user :param _tn: instance of current translator :return: dict() """ LOG.debug("user: %s", db_user.nickname) if db_user.validate_password(PW_FOR_LDAP_USER): # is ldap data = verify_ldap_user_data(db_user.nickname, password, _tn) if data['error']: LOG.debug("Invalid password for the ldap user") return {'error': data['error']} else: return {'user': db_user} # check no-ldap user elif db_user.validate_password(password): return {'user': db_user} else: LOG.debug("Invalid password for the local user") return {'error': _tn.get(_.userPasswordNotMatch)}
def get_reputation_of(db_user: User, only_today=False): """ Return the total sum of reputation_borders points for the given nickname :param db_user: Should be of type "User" :param only_today: Boolean :return: Integer and Boolean, if the user is author """ if not db_user: return 0, False db_reputation = DBDiscussionSession.query(ReputationHistory) if only_today: today = arrow.utcnow().to('Europe/Berlin') db_reputation = db_reputation.filter( ReputationHistory.timestamp >= today) db_reputation = db_reputation.filter_by(reputator_uid=db_user.uid) \ .join(ReputationReason, ReputationReason.uid == ReputationHistory.reputation_uid) \ .all() count = sum([rep.reputations.points for rep in db_reputation]) return count, db_user.is_author() or db_user.is_admin()
def get_reputation_of(db_user: User, only_today=False): """ Return the total sum of reputation_borders points for the given nickname :param db_user: Should be of type "User", but also accepts nickname for legacy support :param only_today: Boolean :return: Integer and Boolean, if the user is author """ if not isinstance(db_user, User): db_user = DBDiscussionSession.query(User).filter_by(nickname=db_user).first() count = 0 if not db_user or db_user.nickname == nick_of_anonymous_user: return count, False db_reputation = DBDiscussionSession.query(ReputationHistory) if only_today: today = arrow.utcnow().to('Europe/Berlin') db_reputation = db_reputation.filter(ReputationHistory.timestamp >= today) db_reputation = db_reputation.filter_by(reputator_uid=db_user.uid) \ .join(ReputationReason, ReputationReason.uid == ReputationHistory.reputation_uid) \ .all() count = sum([r.reputations.points for r in db_reputation]) return count, db_user.is_author() or db_user.is_admin()
def token_to_database(db_user: User, token: Union[str, None]) -> None: """ Store the newly created token in database. :param db_user: User :param token: new token to be stored :return: """ db_user.set_token(token) db_user.update_token_timestamp() transaction.commit()
def demote_user(argv=sys.argv): if len(argv) < 2: print("Please enter a nickname!") sys.exit(1) username: str = argv[1] with transaction.manager: try: User.by_nickname(username).demote_to_user() except NoResultFound: print( f"The user `{username}` does not exist! Make sure you use the private and not the public nickname!" ) sys.exit(1)
def get_issues_overview_for(db_user: User, app_url: str) -> Dict[str, Collection]: """ Returns dictionary with keywords 'user' and 'others', which got lists with dicts with infos IMPORTANT: URL's are generated for the frontend! :param db_user: User :param app_url: current applications url :return: dict """ if not db_user or db_user.nickname == nick_of_anonymous_user: return {'user': [], 'other': []} if db_user.is_admin(): db_issues_other_users = DBDiscussionSession.query(Issue).filter( Issue.author_uid != db_user.uid).all() else: db_issues_other_users = [ issue for issue in db_user.accessible_issues if issue.author_uid != db_user.uid ] db_issues_of_user = DBDiscussionSession.query(Issue).filter_by( author_uid=db_user.uid).order_by(Issue.uid.asc()).all() return { 'user': [__create_issue_dict(issue, app_url) for issue in db_issues_of_user], 'other': [ __create_issue_dict(issue, app_url) for issue in db_issues_other_users ] }
def refresh_public_nickname(user: User) -> str: """ Creates and sets a random public nick for the given user :param user: The user whose nickname shall be refreshed. :return: The new nickname as string """ nick = _random_nickname() while DBDiscussionSession.query(User).filter_by( public_nickname=nick).first(): nick = _random_nickname() LOG.debug("User %s -> %s", user.public_nickname, nick) user.set_public_nickname(nick) return nick
def checks_if_user_is_ldap_user(db_user: User) -> bool: """ Checks if user is ldap user :param db_user :return: """ pw_for_ldap_user = '******' return db_user.validate_password(pw_for_ldap_user)
def __create_new_user(user, ui_locales, oauth_provider='', oauth_provider_id=''): """ Insert a new user row :param user: dict with every information for a user needed :param ui_locales: Language.ui_locales :param oauth_provider: String :param oauth_provider_id: String :return: String, String, User """ success = '' info = '' _t = Translator(ui_locales) # creating a new user with hashed password LOG.debug("Adding user %s", user['nickname']) hashed_password = password_handler.get_hashed_password(user['password']) newuser = User(firstname=user['firstname'], surname=user['lastname'], email=user['email'], nickname=user['nickname'], password=hashed_password, gender=user['gender'], group_uid=user['db_group_uid'], oauth_provider=oauth_provider, oauth_provider_id=oauth_provider_id) DBDiscussionSession.add(newuser) transaction.commit() db_user = DBDiscussionSession.query(User).filter_by( nickname=user['nickname']).first() settings = Settings(author_uid=db_user.uid, send_mails=False, send_notifications=True, should_show_public_nickname=True) DBDiscussionSession.add(settings) transaction.commit() # sanity check, whether the user exists db_user = DBDiscussionSession.query(User).filter_by( nickname=user['nickname']).first() if db_user: LOG.debug("New data was added with uid %s", db_user.uid) success = _t.get(_.accountWasAdded).format(user['nickname']) else: LOG.debug("New data was not added") info = _t.get(_.accoutErrorTryLateOrContant) return success, info, db_user
def set_settings(url, db_user: User, service, settings_value, _tn): """ Edits a user specific setting :param url: current url of request :param db_user: User :param service: service, which should be modified :param settings_value: Boolean :param _tn: Translator :return: public_nick, public_page_url, gravatar_url, error """ error = '' public_nick = db_user.global_nickname db_setting = db_user.settings if service == 'mail': db_setting.set_send_mails(settings_value) elif service == 'notification': db_setting.set_send_notifications(settings_value) elif service == 'public_nick': db_setting.set_show_public_nickname(settings_value) if settings_value: db_user.set_public_nickname(db_user.nickname) elif db_user.nickname == db_user.public_nickname: user.refresh_public_nickname(db_user) public_nick = db_user.global_nickname else: error = _tn.get(_.keyword) transaction.commit() public_page_url = '{}/user/{}'.format(url, db_user.uid) gravatar_url = get_profile_picture(db_user, 80) return { 'error': error, 'public_nick': public_nick, 'public_page_url': public_page_url, 'gravatar_url': gravatar_url }
def __check_in_local_known_user(db_user: User, password: str, _tn) -> dict: """ Tries to check in a local known user. :param db_user: current instance of User :param password: password of the user :param _tn: instance of current translator :return: dict() """ logger('Auth.Login', 'user: {}'.format(db_user.nickname)) if db_user.validate_password(password): return {'user': db_user} if not (db_user.validate_password('NO_PW_BECAUSE_LDAP') or db_user.password is get_hashed_password('NO_PW_BECAUSE_LDAP')): logger('Auth.Login', 'invalid password for the local user') return {'error': _tn.get(_.userPasswordNotMatch)} data = verify_ldap_user_data(db_user.nickname, password, _tn) if data['error']: return {'error': data['error']} return {'user': db_user}
def get_last_issue_of(db_user: User) -> Optional[Issue]: """ Returns the last used issue of the user or None :param db_user: User :return: Issue.uid or 0 """ if not db_user or db_user.is_anonymous(): return None db_issue = db_user.settings.last_topic if not db_issue: return None return None if db_issue.is_disabled else db_issue
def test_user_to_issues(self): db_user: User = User.by_nickname("Björn") issue: Issue = DBDiscussionSession.query(Issue).get(8) self.assertNotIn(issue, db_user.participates_in) db_user.participates_in.append(issue) self.assertIn(issue, db_user.participates_in) association: UserParticipation = DBDiscussionSession.query( UserParticipation).filter_by(user_uid=db_user.uid, issue_uid=issue.uid).one_or_none() self.assertIsNotNone(association) DBDiscussionSession.query(UserParticipation).filter_by( user_uid=db_user.uid, issue_uid=issue.uid).delete()
def __create_new_user(user_info: Dict[str, Any], ui_locales: str, oauth_provider: str = '', oauth_provider_id: str = '') -> Tuple[str, str, User]: """ Create a new user. :param user_info: A dictionary containing information about the desired user. :param ui_locales: Language which shall be used for messaging. :param oauth_provider: If applicable: Which oauth-provider is referring the user. :param oauth_provider_id: If applicable: The ID of the oauth-provider. :return: Returns a tuple containing a success message, a information message and the freshly created user. """ success = '' info = '' _t = Translator(ui_locales) # creating a new user_info with hashed password LOG.debug("Adding user_info for %s", user_info['nickname']) hashed_password = password_handler.get_hashed_password( user_info['password']) new_user = User(firstname=user_info['firstname'], surname=user_info['lastname'], email=user_info['email'], nickname=user_info['nickname'], password=hashed_password, gender=user_info['gender'], group_uid=user_info['db_group_uid'], oauth_provider=oauth_provider, oauth_provider_id=oauth_provider_id) DBDiscussionSession.add(new_user) DBDiscussionSession.flush() settings = Settings(author_uid=new_user.uid, send_mails=False, send_notifications=True, should_show_public_nickname=True) DBDiscussionSession.add(settings) if new_user: LOG.debug("New data was added with uid %s", new_user.uid) success = _t.get(Keywords.accountWasAdded).format( user_info['nickname']) else: LOG.debug("New data was not added") info = _t.get(Keywords.accoutErrorTryLateOrContant) return success, info, new_user
def set_discussions_properties(db_user: User, db_issue: Issue, value, iproperty, translator) -> dict: """ :param db_user: User :param db_issue: Issue :param value: The value which should be assigned to property :param iproperty: Property of Issue, e.g. is_disabled :param translator: :return: """ if db_issue.author_uid != db_user.uid and not db_user.is_admin(): return {'error': translator.get(_.noRights)} if iproperty == 'enable': db_issue.set_disabled(not value) elif iproperty == 'public': db_issue.set_private(not value) elif iproperty == 'writable': db_issue.set_read_only(not value) else: return {'error': translator.get(_.internalKeyError)} return {'error': ''}
def create_speechbubble_dict(bubble_type: BubbleTypes, is_markable: bool = False, is_author: bool = False, uid: str = '', bubble_url: str = '', content: str = '', omit_bubble_url: bool = False, omit_vote_info: bool = False, argument_uid: int = None, statement_uid: int = None, is_supportive: bool = False, db_user: User = None, lang: str = 'en', is_users_opinion: bool = False, other_author: User = None): """ Creates an dictionary which includes every information needed for a bubble. :param bubble_type: BubbleTypes :param is_markable: True if the content itself could be flagged :param is_author: True if the current user is author of the content :param uid: Identifier for the bubble :param bubble_url: URL for the click event of the bubble :param content: Text of the bubble :param omit_bubble_url: True if the bubble should have a link :param omit_vote_info: True if the bubble have the little, grey information text :param argument_uid: Argument.uid :param statement_uid: Statement.uid :param is_supportive: Boolean :param db_user: current :param omit_bubble_url: Boolean :param lang: is_users_opinion :param is_users_opinion: Boolean :param other_author: :return: dict() """ gravatar_link = get_global_url() + '/static/images/icon.png' profile = None is_enemy_user = {'admin': False, 'author': False, 'special': False} if uid != 'now': content = pretty_print_options(content) if bubble_type is BubbleTypes.SYSTEM and other_author is not None: gravatar_link = get_profile_picture(other_author, 25) profile = '/user/{}'.format(other_author.uid), is_enemy_user['admin'] = other_author.is_admin() is_enemy_user['author'] = other_author.is_author() is_enemy_user['special'] = other_author.is_special() # check for users opinion if bubble_type is BubbleTypes.USER and db_user and db_user.nickname != nick_of_anonymous_user: db_marked = None gravatar_link = get_profile_picture(db_user, 25) if argument_uid is not None and db_user is not None: db_marked = DBDiscussionSession.query(MarkedArgument).filter( MarkedArgument.argument_uid == argument_uid, MarkedArgument.author_uid == db_user.uid).first() if statement_uid is not None and db_user is not None: db_marked = DBDiscussionSession.query(MarkedStatement).filter( MarkedStatement.statement_uid == statement_uid, MarkedStatement.author_uid == db_user.uid).first() is_users_opinion = db_marked is not None speech = { 'is_user': bubble_type is BubbleTypes.USER, 'is_system': bubble_type is BubbleTypes.SYSTEM, 'is_status': bubble_type is BubbleTypes.STATUS, 'is_info': bubble_type is BubbleTypes.INFO, 'is_markable': is_markable, 'is_author': is_author, 'is_enemy_user': is_enemy_user, 'id': uid if len(str(uid)) > 0 else uuid4().hex, 'bubble_url': bubble_url, 'message': content, 'omit_bubble_url': omit_bubble_url, 'omit_vote_info': omit_vote_info, 'data_type': 'argument' if argument_uid else 'statement' if statement_uid else 'None', 'data_argument_uid': argument_uid, 'data_statement_uid': statement_uid, 'data_is_supportive': is_supportive, 'is_users_opinion': is_users_opinion, 'enemy': { 'avatar': gravatar_link, 'profile': profile, 'available': profile is not None } } votecount_keys = __get_text_for_click_and_mark_count( db_user, bubble_type is BubbleTypes.USER, argument_uid, statement_uid, speech, lang) speech['votecounts_message'] = votecount_keys[speech['votecounts']] return speech
def prepare_extras_dict(self, current_slug: str, is_reportable: bool, show_bar_icon: bool, show_graph_icon: bool, registry: Registry, application_url: str, path: str, db_user: User, broke_limit=False, add_premise_container_style='display: none', add_statement_container_style='display: none', ongoing_discussion=True): """ Creates the extras.dict() with many options! :param current_slug: :param is_reportable: Same as discussion.bubbles.last.is_markable, but TAL has no last indicator :param show_bar_icon: True, if the discussion space should show the graph icon :param show_graph_icon: True, if the discussion space should show the barometer icon :param registry: Pyramids registry :param application_url: current app url :param path: current path :param db_user: User :param broke_limit: Boolean :param add_premise_container_style: style string, default 'display:none;' :param add_statement_container_style: style string, default 'display:none;' :param ongoing_discussion: Boolean :return: dict() """ LOG.debug("Entering prepare_extras_dict") is_user_from_ldap = False is_logged_in = False nickname = None public_nickname = None is_user_male = False is_user_female = False is_admin = False is_special = False if db_user: is_user_from_ldap = db_user.validate_password(PW_FOR_LDAP_USER) is_logged_in = True nickname = db_user.nickname public_nickname = db_user.public_nickname is_user_male = db_user.gender == 'm' is_user_female = db_user.gender == 'f' is_admin = db_user.is_admin() is_special = db_user.is_special() if db_user.nickname == nick_of_anonymous_user: db_user = None is_logged_in = False return_dict = dict() return_dict['url'] = get_global_url() return_dict['year'] = datetime.datetime.now().year return_dict['restart_url'] = current_slug return_dict['is_in_discussion'] = 'discuss' in path return_dict['logged_in'] = is_logged_in return_dict['nickname'] = nickname return_dict['public_nickname'] = public_nickname return_dict[ 'add_premise_container_style'] = add_premise_container_style return_dict[ 'add_statement_container_style'] = add_statement_container_style return_dict['users_avatar'] = get_profile_picture(db_user, 25) return_dict['ongoing_discussion'] = ongoing_discussion return_dict['slug'] = current_slug return_dict['is_user_male'] = is_user_male return_dict['is_user_female'] = is_user_female return_dict['is_user_neutral'] = not return_dict[ 'is_user_male'] and not return_dict['is_user_female'] return_dict['broke_limit'] = 'true' if broke_limit else 'false' return_dict['use_with_ldap'] = is_user_from_ldap return_dict['development_mode'] = is_development_mode(registry) return_dict['is_development'] = registry.settings.get( 'mode', '') == 'development' return_dict['is_production'] = registry.settings.get( 'mode', '') == 'production' return_dict['review_count'] = get_complete_review_count(db_user) return_dict['modern_bubbles'] = usage_of_modern_bubbles(registry) return_dict['usage_of_matomo'] = usage_of_matomo(registry) self.add_language_options_for_extra_dict(return_dict) is_author, points = get_reputation_of(db_user) is_author_bool = is_author or points > limit_to_open_issues return_dict['is_reportable'] = is_reportable return_dict['is_admin'] = is_admin return_dict['is_special'] = is_special return_dict['is_author'] = is_author_bool return_dict['is_user'] = not (is_admin or is_author_bool or is_special) return_dict['show_bar_icon'] = show_bar_icon return_dict['show_graph_icon'] = show_graph_icon return_dict['close_premise_container'] = True return_dict['close_statement_container'] = True return_dict['date'] = arrow.utcnow().format('DD-MM-YYYY') return_dict['count_of'] = { 'arguments': DBDiscussionSession.query(Argument).count(), 'users': DBDiscussionSession.query(User).count(), 'discussions': DBDiscussionSession.query(Issue).count(), 'reviews': get_count_of_all(), } self.__add_title_text(return_dict, is_logged_in) self.__add_button_text(return_dict) self.__add_tag_text(return_dict) self.__add_login_button_properties(return_dict) message_dict = dict() message_dict['new_count'] = count_of_new_notifications( db_user) if db_user else 0 message_dict['has_unread'] = message_dict['new_count'] > 0 inbox = get_box_for(db_user, self.system_lang, application_url, True) if db_user else [] outbox = get_box_for(db_user, self.system_lang, application_url, False) if db_user else [] message_dict['inbox'] = inbox message_dict['outbox'] = outbox message_dict['total_in'] = len(inbox) message_dict['total_out'] = len(outbox) return_dict['notifications'] = message_dict return return_dict