def test_send_password_recovery_email(self):
        self.register_user(u'panda')
        # 정상적인 상황
        mail_count = len(smtplib.SMTP.mail_list)
        self.engine.member_manager.send_password_recovery_email(u'panda', u'*****@*****.**')
        self.assertEqual(1, len(smtplib.SMTP.mail_list) - mail_count)
        mail_count = len(smtplib.SMTP.mail_list)

        from_addr, to_addrs, msg = smtplib.SMTP.mail_list[-1]
        msg = email.message_from_string(msg).get_payload(decode=True).decode('utf8')

        session = model.Session()
        user = self.engine.member_manager._get_user(session, 'panda')
        codes = user.lost_password_token
        self.assertEqual(1, len(codes))
        session.close()

        if not codes[0].code in msg:
            self.fail("Recovery code is not in the mail content.")

        # 등록되지 않은 유저일때
        try:
            self.engine.member_manager.send_password_recovery_email(u'hodduc', u'*****@*****.**')
            self.fail("Sent password recovery email for non-existing user.")
        except InvalidOperation:
            pass

        # 유저는 맞으나 이메일이 다를때
        try:
            self.engine.member_manager.send_password_recovery_email(u'panda', u'*****@*****.**')
            self.fail("Sent password recoveryt email for wrong email address.")
        except InvalidOperation:
            pass

        # 다시 보내면 다른 코드로 갱신되어야 함
        self.engine.member_manager.send_password_recovery_email(u'panda', u'*****@*****.**')
        self.assertEqual(1, len(smtplib.SMTP.mail_list) - mail_count)
        from_addr, to_addrs, new_msg = smtplib.SMTP.mail_list[-1]
        new_msg = email.message_from_string(new_msg).get_payload(decode=True).decode('utf8')

        self.assertNotEqual(new_msg, msg)

        session = model.Session()
        user = self.engine.member_manager._get_user(session, 'panda')
        new_codes = user.lost_password_token
        self.assertEqual(1, len(new_codes))
        session.close()

        if codes[0].code in new_msg:
            self.fail("Recovery code is not flushed.")
        if not new_codes[0].code in new_msg:
            self.fail("Recovery code is not in the mail content.")
Exemple #2
0
    def get_activated_users(self, session_key, limit=-1):
        '''
        전체 사용자들 중 사용자 인증이 된 사용자들의 목록을 돌려준다.
        SYSOP 만 사용 가능.

        @type  session_key: string
        @param session_key: 사용자 Login Session
        @type  limit: int
        @param limit: 최대 몇 명의 사용자를 돌려줄 것인가. -1 일 때는 모든 사용자
        @rtype: list<arara_thrift.SearchUserResult>
        @return: 사용자 인증이 된 사용자들의 목록
        '''
        if not self.is_sysop(session_key):
            raise InvalidOperation('not sysop')

        session = model.Session()
        query = session.query(model.User).filter_by(activated=True)
        users = query.all()
        # 갯수 제한 설정
        if limit > len(users):
            limit = len(users)

        result = [None] * limit

        for idx, user in enumerate(users):
            if limit == idx:  # limit == -1 이면 절대 여기 걸리지 않는다
                break  # 한편 그 외의 경우엔 limit 갯수만큼만 통과
            result[idx] = SearchUserResult(
                **self._get_dict(user, USER_SEARCH_WHITELIST))

        session.close()

        return result
Exemple #3
0
    def change_listing_mode(self, session_key, listing_mode):
        '''
        로그인한 user의 listing mode (글 목록 정렬 방식) 를 변경한다.

        @type  session_key: string
        @param session_key: 사용자 Login Session (must be SYSOP)
        @type  listing_mode: int
        @param listing_mode: 글 목록 정렬 방식 (ArticleManager 참고)
        @return:
            1. 성공했을 경우: void
            2. 실패했을 경우 : Invalid Operation
        '''
        if listing_mode < 0 or 1 < listing_mode:
            raise InvalidOperation('wrong listing mode')

        session = model.Session()
        user = self._get_user_by_session(session, session_key)
        user_id = user.id
        try:
            user.listing_mode = listing_mode
            session.commit()
            session.close()
        except InvalidRequestError:
            session.close()
            raise InvalidOperation('database error')

        # Cache update
        ara_memcached.clear_memcached(self.get_listing_mode, user_id)
Exemple #4
0
    def user_to_sysop(self, session_key, username):
        '''
        user를 SYSOP으로 바꿔주는 함수

        @type  session_key: string
        @param session_key: 사용자 Login Session (must be SYSOP)
        @type username_string
        @param username: Username that will be SYSOP
        @return:
            1. 성공했을 경우: void
            2. 실패했을 경우: Invalid Operation
        '''
        # TODO: 사용자 쿼리 밖으로 빼기
        # TODO: sysop 인지 체크하는 거 밖으로 빼기

        if not self.is_sysop(session_key):
            raise InvalidOperation('no permission')

        username = smart_unicode(username)
        session = model.Session()

        user = self._get_user(session, username, 'user does not exist')
        if user.is_sysop:
            session.close()
            raise InvalidOperation('already sysop..')
        user.is_sysop = True
        session.commit()
        session.close()
Exemple #5
0
    def send_id_recovery_email(self, email):
        '''
        ID를 잃어버렸을 때, e-mail 기반으로 id를 찾아서 그 이메일로 id를 전송해주는 함수.
        성공할 경우 True, 실패할 경우 False를 반환한다.

        @type  email: string
        @param email: 이메일 주소
        @rtype: bool
        @return:
            1. 성공 시 : True
            2. 실패 시 : False
        '''
        session = model.Session()
        query = session.query(model.User).filter_by(email=email)
        try:
            user = query.one()
            session.close()
        except NoResultFound:
            session.close()
            return False

        title = arara_settings.MAIL_TITLE['id_recovery']
        content = arara_settings.MAIL_CONTENT['id_recovery']
        content += ' Here is your ARA account username which is associated with %s <br /><br /> ' % email
        content += '    Your ID  :  %s   <br /><br />' % user.username
        content += ' Please visit http://' + arara_settings.WARARA_SERVER_ADDRESS + '<br /><br />'
        content += ' This is post-only mailing. <br /> Thanks. '
        send_mail(title, email, content)

        return True
Exemple #6
0
    def get_welcome(self):
        '''
        welcome 가져오는 함수

        >>> notice.get_welcome()
        '<html> .... '

        @rtype: string
        @return:
            1. welcome 있을 때: 랜덤하게 선택된 welcome(html)
            2. welcome 없을 때: InvalidOperation Exception
        '''
        session = model.Session()
        available_welcome = session.query(
            model.Welcome).filter_by(valid=True).all()
        available_welcome_dict_list = self._get_dict_list(
            available_welcome, NOTICE_PUBLIC_WHITELIST)
        if available_welcome_dict_list:
            weight_welcome = []
            for index in range(len(available_welcome_dict_list)):
                for weight in range(available_welcome_dict_list[index].weight):
                    weight_welcome.append(index)
            n = random.choice(weight_welcome)
            session.close()
            return available_welcome_dict_list[n].content
        else:
            session.close()
            raise InvalidOperation('no welcome')
Exemple #7
0
    def set_selected_boards(self, session_key, board_ids):
        '''
        boards_id로 주어진 게시판들을 주어진 사용자의 즐겨찾는 게시판으로 설정한다

        @type  session_key: string
        @param session_key: 사용자 Login Session
        @type  board_ids: list<int>
        @param board_ids: 게시판들의 아이디 목록
        @rtype: void
        @return: None
        '''
        session = model.Session()
        user = self._get_user_by_session(session, session_key)

        if len(board_ids) > 3:
            session.close()
            raise InvalidOperation("Please check 3 boards at most")
        try:
            boards = [
                session.query(model.Board).filter_by(id=x).one()
                for x in board_ids
            ]
        except NoResultFound, MultipleResultsFound:
            session.close()
            raise InvalidOperation("Not a valid board id")
Exemple #8
0
    def query_by_nick(self, session_key, nickname):
        '''
        nickname 기반 쿼리 함수. 다른 사용자의 정보를 알아내는 데 사용한다.


        @type  session_key: string
        @param session_key: 사용자 Login Session
        @type  username: string
        @param nickname: User Nickname to send Query
        @rtype: ttypes.PublicUserInformation
        @return:
            1. 쿼리 성공: query_dic
            2. 쿼리 실패:
                1. 존재하지 않는 닉네임: InvalidOperation('QUERY_NICK_NOT_EXIST'
                2. 로그인되지 않은 유저: InvalidOperation('NOT_LOGGEDIN'
                3. 데이터베이스 오류: InvalidOperation('DATABASE_ERROR'
        '''
        # TODO: 쿼리 밖으로 빼기
        nickname = smart_unicode(nickname)
        session = model.Session()
        try:
            query_user = session.query(model.User).filter_by(
                nickname=nickname).filter_by(deleted=False).one()
            query_user_dict = filter_dict(query_user.__dict__,
                                          USER_QUERY_WHITELIST)
            if query_user_dict['last_logout_time']:
                query_user_dict['last_logout_time'] = datetime2timestamp(
                    query_user_dict['last_logout_time'])
            else:
                query_user_dict['last_logout_time'] = 0
            session.close()
            return PublicUserInformation(**query_user_dict)
        except InvalidRequestError:
            session.close()
            raise InvalidOperation('query nickname does not exist')
Exemple #9
0
    def list_welcome(self, session_key):
        '''
        관리자용 welcome 페이지 목록을 가져오는 함수

        >>> notice.list_welcome(SYSOP_session_key)
        [{'no': 32, 'content': '신입회원을 모집합니다','availability': 'True'}, {'no': 33', content': '환영합니다','availability': 'False'}

        @rtype: list
        @return:
            1. welcome 페이지가 있을 때: True, welcome 페이지들의 목록(text)
            2. welcome 페이지가 없을 때: 
                1. welcome 없을때   : False, 'NO_WELCOME'
                2. 데이터베이스 오류: False, 'DATABASE_ERROR'
            3. 시삽이 아닐 때: False, 'NOT_SYSOP'
        '''

        if not self.engine.member_manager.is_sysop(session_key):
            raise InvalidOperation('not sysop')
        session = model.Session()
        welcome = session.query(model.Welcome).all()
        welcome_dict_list = self._get_dict_list(welcome,
                                                NOTICE_PUBLIC_WHITELIST)

        if welcome_dict_list:
            session.close()
            return welcome_dict_list
        else:
            session.close()
            raise InvalidOperation('no welcome')
Exemple #10
0
    def delete_file(self, session_key, article_id, file_id):
        '''
        지울 파일이 저장된 장소와 저장된 파일명을 리턴해주는 함수
        
        @type  session_key: string
        @param session_key: 사용자 Login Session
        @type  article_id: int
        @param article_id: Article Number 
        @type  file_id: int
        @param file_id: File 번호
        @rtype: ttypes.FileInfo
        @return:
            1. 성공: {'file_path': 'blah/blah', 'saved_filename': 'blah'}
            2. 실패:
                1. 로그인되지 않은 유저: False, 'NOT_LOGGEDIN'
                2. 데이터베이스 오류: False, 'DATABASE_ERROR'
        '''
        # TODO: download_file함수와 유사하다.. 똑같은 코드가 많다.. 먼가 비효율적이다.. 나중에 하나로 좀 해보자.. 일단 지금은 급하니까.. 복사해놓고...
        #ret, filepath_to_delete= self.download_file(session_key, article_id, filename)
        session = model.Session()
        article = self._get_article(session, article_id)
        file = self._get_file(session, file_id, article)

        file.deleted = True
        download_path = file.filepath
        ghost_filename = file.saved_filename
        session.commit()
        session.close()
        return FileInfo(download_path, ghost_filename)
Exemple #11
0
    def delete_blacklist(self, session_key, username):
        '''
        현재 로그인한 사용자가 차단 해제하고자 하는 사용자를 Blacklist 에서 제거한다.

        @type  session_key: string
        @param session_key: 사용자 Login Session
        @type  username: string
        @param username: 차단을 해제하고자 하는 사용자의 username
        @rtype: void
        @return:
            1. 삭제 성공: void 
            2. 삭제 실패:
                1. 블랙리스트에 존재하지 않는 아이디: InvalidOperation Exception 
                2. 로그인되지 않은 사용자: InvalidOperation Exception
                3. 데이터베이스 오류: InternalError Exception
        '''
        # TODO: user_id 를 파라메터로 하는 함수 분리
        user_id = self.engine.login_manager.get_user_id(session_key)
        username = smart_unicode(username)

        session = model.Session()
        blacklisted_user = self.engine.member_manager._get_user(
            session, username)

        try:
            blacklist_to_del = session.query(model.Blacklist).filter_by(
                user_id=user_id,
                blacklisted_user_id=blacklisted_user.id).one()
        except InvalidRequestError:
            session.close()
            raise InvalidOperation('username not in blacklist')
        session.delete(blacklist_to_del)
        session.commit()
        session.close()
        return
Exemple #12
0
    def get_blacklist(self, session_key):
        '''
        로그인한 사용자의 블랙리스트 목록을 돌려준다.

        @type  session_key: string
        @param session_key: 사용자 Login Session
        @rtype: list<ttypes.BlacklistInformation>
        @return:
            1. 성공: BlacklistInformation 의 List
            2. 실패:
                1. 로그인되지 않은 사용자:InvalidOperation 'NOT_LOGGEDIN'
                2. 데이터베이스 오류: InternalError 'DATABASE_ERROR'
        '''
        # TODO: user_id 를 파라메터로 하는 함수 분리
        user_id = self.engine.login_manager.get_user_id(session_key)
        try:
            session = model.Session()
            blacklist_list = session.query(
                model.Blacklist).filter_by(user_id=user_id).all()
            session.close()
            blacklist_list = self._get_dict_list(blacklist_list,
                                                 BLACKLIST_LIST_DICT)
        except:
            session.close()
            raise InternalError('database error')
        return blacklist_list
Exemple #13
0
    def read_sent_message(self, session_key, msg_no):
        '''
        쪽지 하나 읽어오기

        @type  session_key: string
        @param session_key: 사용자 Login Session
        @type  msg_no: int
        @param msg_no: Message Number
        @rtype: dictionary
        @return:
            1. 읽어오기 성공: Message
            2. 읽어오기 실패:
                1. 메세지가 존재하지 않음: InvalidOperation Exception
                2. 로그인되지 않은 사용자: NotLoggedIn Exception
                3. 데이터베이스 오류: InternalError Exception
        '''
        # TODO: 쿼리 부분 분리하여 좀더 함수 조립식으로 만들기
        
        user_info = self.engine.login_manager.get_session(session_key)
        session = model.Session()
        from_user = self.engine.member_manager._get_user(session, user_info.username)
        try:
            message = session.query(model.Message).filter(and_(model.Message.from_id==from_user.id, model.Message.id==msg_no, not_(model.Message.sent_deleted==True))).one()
        except InvalidRequestError:
            session.close()
            raise InvalidOperation('message not exist')
        message_dict = self._get_dict(message, MESSAGE_WHITELIST)
        message.read_status = u'R'
        session.commit()
        session.close()
        return Message(**message_dict)
Exemple #14
0
    def test_cleanup_expired_sessions(self):
        # 테스트 상황 설계
        # 1) 2명의 사용자 모두 ReadStatus 가 로드되어 있음
        # 2) 이중 1명만 Session 이 Expire 되어야 함
        session_key_panda = self.register_and_login(u'panda')  # user 2
        session_key_sillo = self.register_and_login(u'sillo')  # user 3
        self.engine.read_status_manager._initialize_data(2)
        self.engine.read_status_manager._initialize_data(3)
        time.time.elapse(SESSION_EXPIRE_TIME + 1.0)
        self.engine.login_manager.update_session(session_key_sillo)

        self.engine.login_manager.cleanup_expired_sessions()

        # LoginManager
        self.assertEqual(
            {
                session_key_sillo: {
                    'username': u'sillo',
                    'current_action': 'login_manager.login()',
                    'ip': u'127.0.0.1',
                    'logintime': 1.1000000000000001,
                    'last_action_time': 3612.0999999999999,
                    'nickname': u'sillo',
                    'id': 3
                }
            }, self.engine.login_manager.session_dic)
        # MemberManager
        expect = datetime.datetime.fromtimestamp(1.1 + SESSION_EXPIRE_TIME + 1)
        result = model.Session().query(model.User).filter_by(id=2).one()
        self.assertEqual(expect, result.last_logout_time)
        # ReadStatusManager
        self.assertEqual([3],
                         self.engine.read_status_manager.read_status.keys())
        self.assertEqual([(0, 'N')],
                         self.engine.read_status_manager.read_status[3].data)
Exemple #15
0
    def query_by_username(self, session_key, username):
        '''
        username 기반 쿼리 함수. 다른 사용자의 정보를 알아내는 데 사용한다.

        @type  session_key: string
        @param session_key: 사용자 Login Session
        @type  username: string
        @param username: User ID to send Query
        @rtype: ttypes.PublicUserInformation
        @return:
            1. 쿼리 성공: query_dic
            2. 쿼리 실패:
                1. 존재하지 않는 아이디: InvalidOperation('QUERY_ID_NOT_EXIST')
                2. 로그인되지 않은 유저: InvalidOperation('NOT_LOGGEDIN')
                3. 데이터베이스 오류: InvalidOperation('DATABASE_ERROR')
        '''
        # TODO: Exception 내용 정정
        username = smart_unicode(username)
        session = model.Session()
        query_user = self._get_user(session, username,
                                    'Query username does not exist')
        query_user_dict = filter_dict(query_user.__dict__,
                                      USER_QUERY_WHITELIST)
        if query_user_dict['last_logout_time']:
            query_user_dict['last_logout_time'] = datetime2timestamp(
                query_user_dict['last_logout_time'])
        else:
            query_user_dict['last_logout_time'] = 0
        session.close()
        return PublicUserInformation(**query_user_dict)
Exemple #16
0
    def cancel_confirm(self, username):
        '''
        사용자의 이메일 인증을 해제하고 다른 사용자가 해당 이메일을 사용할 수 있도록 함

        @type  username: string
        @param username: 사용자의 User ID
        @rtype: None
        @return: None
        '''

        username_ = smart_unicode(username)

        session = model.Session()
        user = self._get_user(session, username, 'user does not exist')

        if not user.activated:
            raise InvalidOperation('Not confirmed')

        key = (user.username + user.nickname + str(time.time()))
        activation_code = hashlib.md5(key).hexdigest()

        try:
            user_activation = model.UserActivation(user, activation_code)
            session.add(user_activation)

            user.activated = False
            user.email = u''
            session.commit()
        except IntegrityError:
            session.rollback()
            session.close()
            raise InvalidOperation('already canceled')
        except:
            raise InternalError('database error')
Exemple #17
0
    def get_banner(self):
        '''
        배너를 가져오는 함수

        >>> notice.get_banner()
        '<html> .... '

        @rtype: string
        @return:
            1. 배너가 있을 때: 랜덤하게 선택된 배너(html)
            2. 배너가 없을 때: InvalidOperation Exception
        '''
        session = model.Session()
        available_banner = session.query(
            model.Banner).filter_by(valid=True).all()
        available_banner_dict_list = self._get_dict_list(
            available_banner, NOTICE_PUBLIC_WHITELIST)
        if available_banner_dict_list:
            weight_banner = []
            for index in range(len(available_banner_dict_list)):
                for weight in range(available_banner_dict_list[index].weight):
                    weight_banner.append(index)
            n = random.choice(weight_banner)
            session.close()
            return available_banner_dict_list[n].content
        else:
            session.close()
            raise InvalidOperation('no banner')
Exemple #18
0
    def _register_without_confirm(self, user_reg_dic, is_sysop):
        '''
        confirm 과정 없이 사용자를 활성화된 상태로 등록하는 함수

        @type  user_reg_dic: dict('username', 'password', 'nickname', 'email', 'signature', 'self_introduction', 'default_language', 'campus')
        @param user_reg_dic: User Information
        @type  is_sysop: bool
        @param is_sysop: 유저가 시삽권한을 가질지를 결정
        @rtype: void
        @return:
            1. 사용자 등록이 성공했을 경우 : void
            2. 사용자 등록이 실패했을 경우 : Invalid Operation
        '''
        # TODO: 예외 상황이 여러 가지가 있을 수 있다. DB 자체 에러, 이미 등록된 유저 등. 나누어야 한다.
        try:
            user = model.User(**user_reg_dic)
            session = model.Session()
            session.add(user)
            user.activated = True
            user.is_sysop = is_sysop
            session.commit()
            session.close()
        except:
            session.rollback()
            session.close()
            import traceback
            self.logger.exception("Special Exception : \n%s",
                                  traceback.format_exc())
            raise InvalidOperation('Cannot add users without confirm')
Exemple #19
0
    def modify_password_sysop(self, session_key, user_password_info):
        '''
        회원의 password를 시삽이 강제로 수정.

        @type  session_key: string
        @param session_key: 사용자 Login Session (SYSOP)
        @type  user_password_info: ttypes.UserPasswordInfo
        @param user_password_info: 사용자의 비밀번호 정보
        @rtype: void
        @return:
            1. modify 성공: void
            2. modify 실패:
                1. 로그인되지 않은 사용자: NotLoggedIn
                2. 사용자가 존재하지 않을 경우: InvalidOperation('user does not exist')
                3. 수정 권한 없음: InvalidOperation('no permission')
                4. 데이터베이스 오류: InvalidOperation('DATABASE_ERROR')
        '''
        # TODO: 쿼리 밖으로 빼기
        # TODO: check_sysop 구현하여 그걸 쓰기
        if not self.is_sysop(session_key):
            raise InvalidOperation('no permission')

        username = smart_unicode(user_password_info.username)
        session = model.Session()
        user = self._get_user(session, username, 'user does not exist')
        user.set_password(user_password_info.new_password)
        session.commit()
        self.logger.info(u"PASSWORD CHANGE:(username=%s)" % username)
        session.close()
Exemple #20
0
    def get_info(self, session_key):
        '''
        회원 정보 수정을 위해 현재 로그인된 회원 자신의 정보를 가져오는 함수.
        다른 사용자의 정보를 열람하는 query와 다름.

        @type  session_key: string
        @param session_key: 사용자 Login Session
        @rtype: ttypes.UserInformation
        @return:
            1. 가져오기 성공: user_dic
            2. 가져오기 실패:
                1. 로그인되지 않은 유저: InvalidOperation('NOT_LOGGEDIN')
                2. 존재하지 않는 회원: InvalidOperation('MEMBER_NOT_EXIST')
                3. 데이터베이스 오류: InvalidOperation('DATABASE_ERROR')
        '''
        session = model.Session()
        username = self.engine.login_manager.get_session(session_key).username
        username = smart_unicode(username)
        user = self._get_user(session, username, 'member does not exist')
        user_dict = filter_dict(user.__dict__, USER_PUBLIC_WHITELIST)
        if user_dict['last_logout_time']:
            user_dict['last_logout_time'] = datetime2timestamp(
                user_dict['last_logout_time'])
        else:
            user_dict['last_logout_time'] = 0
        session.close()
        return UserInformation(**user_dict)
Exemple #21
0
    def download_file(self, article_id, file_id):
        '''
        article의 파일을 다운로드 할때 실제로 파일이 저장된 장소와 저장된 파일명을 리턴해주는 함수 
        
        @type  article_id: int
        @param article_id: Article Number 
        @type  file_id: int
        @param file_id: 다운로드하려는 파일의 번호
        @rtype: ttypes.DownloadFileInfo
        @return:
            1. 경로 찾기 성공: {'file_path': blah, 'saved_filename': blah, 'real_filename': blah}
            2. 경로 찾기 실패:
                1. 로그인되지 않은 유저: NotLoggedIn Exception
                2. 데이터베이스 오류: InternalError Exception
        '''
        # TODO: 아래 commit 이 왜 필요한지 알아보기
        session = model.Session()
        article = self._get_article(session, article_id)
        file = self._get_file(session, file_id, article)

        download_path = file.filepath
        ghost_filename = file.saved_filename
        real_filename = file.filename
        session.commit()
        session.close()
        return DownloadFileInfo(download_path, ghost_filename, real_filename)
Exemple #22
0
    def send_message_by_nickname(self, session_key, to_nickname, msg):
        '''
        해당 하는 nickname을 갖는 사용자에게 쪽지를 전송하는 함수 

        @type  session_key: string
        @param session_key: 사용자 Login Session
        @type  to_nickname: string
        @param to_nickname: Destination nickname
        @type  msg: string
        @param msg: Message string
        @rtype: void
        @return:
            1. 메세지 전송 성공: void
            2. 메세지 전송 실패:
                1. 보낼 아이디가 존재하지 않음: InvalidOperation Exception
                2. 로그인되지 않은 사용자: NotLoggedIn Exception
                3. 데이터베이스 오류: InternalError Exception
        '''

        user_info = self.engine.login_manager.get_session(session_key)
        session = model.Session()
        to_user = self._get_user_by_nickname(session, to_nickname)
        from_user = self.engine.member_manager._get_user(session, user_info.username)
        from_user_ip = user_info.ip
        message = model.Message(from_user, from_user_ip, to_user, msg)
        try:
            session.add(message)
            session.commit()
        except InvalidRequestError:
            session.close()
            raise InternalError('database error')
        session.close()
Exemple #23
0
    def receive_list(self, session_key, page=1, page_length=20):
        '''
        @type  session_key: string
        @param session_key: 사용자 Login Session
        @type  page: int
        @param page: Page Number
        @type  page_length: int
        @param page_length: Number of Messages to get in one page
        @rtype: ttypes.MessageList
        @return:
            1. 리스트 읽어오기 성공: MessageList
            2. 리스트 읽어오기 실패:
                1. 로그인되지 않은 사용자: NotLoggedIn Exception
                2. 데이터베이스 오류: InternalError Exception
        '''
        # TODO: ArticleManager 참고하여 싹 뜯어고치기
        # TODO: page 관련 정보 처리하는거 ArticleManager 에서 아예 util 로 옮기기

        ret_dict = {}
        user_info = self.engine.login_manager.get_session(session_key)
        session = model.Session()
        to_user = self.engine.member_manager._get_user(session, user_info.username)
        blacklist_dict_list = self.engine.blacklist_manager.get_blacklist(session_key)
        blacklist_users = set()
        for blacklist_item in blacklist_dict_list:
            if blacklist_item.block_message:
                blacklist_users.add(blacklist_item.blacklisted_user_username)
        received_messages_count = session.query(model.Message).filter(
                and_(model.Message.to_id==to_user.id,
                    not_(model.Message.received_deleted==True)
                    )).count()
        received_new_messages_count = session.query(model.Message).filter(
                and_(model.Message.to_id==to_user.id,
                    model.Message.read_status==u'N',
                    not_(model.Message.received_deleted==True)
                    )).count()
        last_page = int(received_messages_count / page_length)
        page = int(page)
        if received_messages_count % page_length != 0:
            last_page += 1
        elif received_messages_count == 0:
            last_page += 1
        if page > last_page:
            session.close()
            raise InvalidOperation('wrong pagenum')
        offset = page_length * (page - 1)
        last = offset + page_length
        received_messages = session.query(model.Message).filter(
                and_(model.Message.to_id==to_user.id, 
                    not_(model.Message.received_deleted==True)
                    )).order_by(model.Message.id.desc())[offset:last]
        received_messages_dict_list = self._get_dict_list(received_messages, MESSAGE_WHITELIST, blacklist_users)
        ret_dict['hit'] = received_messages_dict_list
        ret_dict['last_page'] = last_page
        ret_dict['new_message_count'] = received_new_messages_count
        ret_dict['results'] = received_messages_count
        session.close()
        return MessageList(**ret_dict)
Exemple #24
0
 def __contains__(self, key):
     session = model.Session()
     try:
         login_session = session.query(model.LoginSession).filter_by(session_key=key).one()
         session.close()
         return True
     except NoResultFound:
         session.close()
         return False
Exemple #25
0
 def __getitem__(self, key):
     session = model.Session()
     try:
         login_session = session.query(model.LoginSession).filter_by(session_key=key).one()
         session.close()
         return login_session.session_data
     except NoResultFound:
         session.close()
         raise KeyError()
Exemple #26
0
 def __setitem__(self, key, value):
     session = model.Session()
     try:
         # 로그인되어 있는 사용자의 경우 DB의 해당 row에 새로운 값을 기록한다
         login_session = session.query(model.LoginSession).filter_by(session_key=key).one()
         login_session.session_data = value
     except NoResultFound:
         # 로그인되어 있지 않은 사용자의 경우 DB에 새로운 row를 생성한다
         login_session = model.LoginSession(key, value, datetime.datetime.now())
         session.add(login_session)
     session.commit()
     session.close()
Exemple #27
0
    def authenticate(self, username, password, user_ip):
        '''
        사용자가 입력한 password 로 검사한다.

        @type  username: string
        @param username: 사용자의 id
        @type  password: string
        @param password: 사용자의 비밀번호
        @type  user_ip: string
        @param user_ip: 사용자의 IP 주소
        '''
        # TODO: user 쿼리 밖으로 빼기
        # TODO: ret 딕셔너리 만드는 코드 다듬기
        # TODO: 궁극적으로 비밀번호 저장방식 바꾸기
        username = smart_unicode(username)
        if username.strip() == u"" or username == u" ":
            raise InvalidOperation('wrong username')
        session = model.Session()
        user = self._get_user(session, username, 'wrong username')
        try:
            if user.compare_password(password):
                if user.activated:
                    current_time = time.time()
                    user.last_login_time = datetime.datetime.fromtimestamp(
                        current_time)
                    user.last_login_ip = unicode(user_ip)
                    ret = {
                        'last_login_time': current_time,
                        'nickname': user.nickname,
                        'id': user.id
                    }
                    if user.lost_password_token:
                        for tok in user.lost_password_token:
                            session.delete(tok)
                    session.commit()
                    session.close()
                    return AuthenticationInfo(**ret)
                else:
                    session.close()
                    raise InvalidOperation(u'not activated\n%s\n%s' %
                                           (user.username, user.nickname))
            else:
                session.close()
                raise InvalidOperation('wrong password')
        except InvalidOperation:
            raise
        except Exception, e:
            self.logger.warning(
                "Exception occur on member_manager.authenticate. username <%s> and Error <%s>"
                % (username, repr(e)))
            raise InvalidOperation(
                "unexpected error on authentication, contact SYSOP")
Exemple #28
0
    def test_update_last_logout_time(self):
        # 2명의 사용자를 등록한다
        self.register_user(u'panda')     # user 2
        self.register_user(u'bbashong')  # user 3

        # 시삽과 이 2명의 사용자의 로그아웃 시간을 업데이트한다
        self.engine.member_manager.update_last_logout_time([1, 2, 3])
        # 사용자들의 로그아웃 시간이 잘 업데이트되었는지 확인
        time_1 = datetime.datetime.fromtimestamp(time.time())
        users = model.Session().query(model.User).order_by(model.User.id.asc()).all()
        self.assertEqual(time_1, users[0].last_logout_time)
        self.assertEqual(time_1, users[1].last_logout_time)
        self.assertEqual(time_1, users[2].last_logout_time)

        # 두 사용자만 업데이트하고 둘만 변화했는지 확인
        time.time.elapse(1)
        self.engine.member_manager.update_last_logout_time([1, 3])
        time_2 = datetime.datetime.fromtimestamp(time.time())
        users = model.Session().query(model.User).order_by(model.User.id.asc()).all()
        self.assertEqual(time_2, users[0].last_logout_time)
        self.assertEqual(time_1, users[1].last_logout_time)
        self.assertEqual(time_2, users[2].last_logout_time)
Exemple #29
0
    def search_user(self, session_key, search_user, search_key=None):
        '''
        찾고자 하는 username와 nickname에 해당하는 user를 찾아주는 함수
        search_key 가 username 또는 nickname 으로 주어질 경우 해당하는 search key로만 찾는다
        (주어지지 않으면 두 방향 모두에 대하여 찾는다)

        @type  session_key: string
        @param session_key: 사용자 Login Session
        @type  search_user: string
        @param search_user: User Info(username or nickname)
        @type  search_key: string
        @param search_key: Search key
        @rtype: list<ttypes.SearchUserResult>
        @return:
            1. 성공시: True, {'username':'******','nickname':'mikkang'}
            2. 실패시:
                1. 존재하지 않는 사용자: InvalidOperation('NOT_EXIST_USER'
                2. 잘못된 검색 키:InvalidOperation('INCORRECT_SEARCH_KEY')
        '''
        # TODO: session_key 를 이용한 Login check
        # TODO: 쿼리 직접 쓰지 말고 나머지 두 함수 합쳐서 할 것
        # TODO: SearchUserResult 는 뭐고 PublicUserInformation 는 뭔가?
        search_user = smart_unicode(search_user)

        session = model.Session()
        try:
            if not search_key:
                user = session.query(model.User).filter(
                    or_(model.User.username == search_user,
                        model.User.nickname == search_user)).filter_by(
                            deleted=False).all()
            else:
                if search_key.lower() == u'username':
                    user = session.query(model.User).filter_by(
                        username=search_user).filter_by(deleted=False).all()
                elif search_key.lower() == u'nickname':
                    user = session.query(model.User).filter_by(
                        nickname=search_user).filter_by(deleted=False).all()
                else:
                    session.close()
                    raise InvalidOperation('incorrect search key')
            user_dict_list = self._get_dict_list(user, USER_SEARCH_WHITELIST)
            user_list = [SearchUserResult(**x) for x in user_dict_list]
            session.close()
            return user_list
        except InvalidRequestError:
            session.close()
            raise InvalidOperation('user does not exist')
        except AssertionError:
            session.close()
            raise InvalidOperation('invalid key')
Exemple #30
0
    def add_blacklist(self,
                      session_key,
                      username,
                      block_article=True,
                      block_message=True):
        '''
        현재 로그인한 사용자가 차단하고자 하는 새로운 사용자를 Blacklist 에 추가한다.

        @type  session_key: string
        @param session_key: 사용자 Login Session
        @type  username: string
        @param username: 차단하고자 하는 사용자의 username
        @type  block_article: bool
        @param block_article: 해당 사용자의 글을 읽지 않을 것인지의 여부
        @type  block_message: bool
        @param block_message: 해당 사용자의 메시지를 받지 않을 것인지의 여부
        @rtype: void
        @return:
            1. 추가 성공: void
            2. 추가 실패:
                1. Wrong Dictionary: InvalidOperation Exception
                2. 존재하지 않는 아이디: InvalidOperation Exception 
                3. 자기 자신은 등록 불가: InvalidOperation Exception 
                4. 이미 추가되어있는 아이디: InvalidOperation Exception
                5. 로그인되지 않은 사용자: NotLoggedIn Exception
                6. 데이터베이스 오류: InternalError Exception 
        '''
        # TODO: 시삽을 차단하게 허용할 것인가?
        # TODO: block_article, block_message 가 모두 False 라면?
        # TODO: user_id 를 파라메터로 하는 함수 분리
        user_info = self.engine.login_manager.get_session(session_key)
        username = smart_unicode(username)
        if username == user_info.username:
            raise InvalidOperation('cannot add yourself')

        session = model.Session()
        user = self.engine.member_manager._get_user(session,
                                                    user_info.username)
        target_user = self.engine.member_manager._get_user(session, username)

        integrity_chk = session.query(model.Blacklist).filter_by(
            user_id=user.id, blacklisted_user_id=target_user.id).all()
        if integrity_chk:
            session.close()
            raise InvalidOperation('already added')
        new_blacklist = model.Blacklist(user, target_user, block_article,
                                        block_message)
        session.add(new_blacklist)
        session.commit()
        session.close()
        return