def add_thread_and_post(user_id, forum, thread_title, post_body): result = enki.libutil.ENKILIB_OK if user_id and forum and thread_title and post_body: if len(thread_title) <= THREAD_TITLE_LENGTH_MAX and len( post_body) <= POST_LENGTH_MAX: if enki.libdisplayname.get_EnkiUserDisplayName_by_user_id_current( user_id): thread = EnkiModelThread(author=user_id, forum=int(forum), title=thread_title, num_posts=1) thread.put() post = EnkiModelPost(author=user_id, body=post_body, thread=thread.key.id()) post.put() forum_selected = ndb.Key(EnkiModelForum, int(forum)).get() forum_selected.num_posts += 1 forum_selected.num_threads += 1 forum_selected.put() else: result = ERROR_POST_CREATION else: result = ERROR_POST_LENGTH else: result = ERROR_POST_CREATION return result
def get( self, post ): data = '' not_found = '' is_author = False post_body = '' self.session[ 'sessionrefpath' ] = self.request.referrer if post.isdigit() and EnkiModelPost.get_by_id( int( post ) ): data = EnkiModelPost.get_post_data( post ) if data: is_author = True if self.user_id == data.author_data.user_id else False post_body = '' if data.post.body == EnkiModelPost.POST_DELETED else data.post.body else: not_found = MSG.POST_NOT_EXIST( ) change = self.request.get( 'change' ) CSRFneeded = True if change != 'edit' and change != 'delete': CSRFneeded = False self.render_tmpl( 'post.html', CSRFneeded, active_menu = 'forums', data = data, not_found = not_found, change = change, isauthor = is_author, has_permission_sticky = self.has_permissions( self.enki_user, [ 'PFPS' ]), postbody = post_body, maxpostlength = EnkiModelPost.POST_LENGTH_MAX )
def delete_account(self, delete_posts=False, token=''): token_to_save = 'accountdelete' if not token: # there is no token if the user has no email address: they are deleted immediately. They must be logged in. user_to_delete = self.enki_user else: # a user has followed a accountdelete token link. The user account associated with the token will be deleted tokenEntity = EnkiModelTokenVerify.get_by_token(token) user_to_delete = EnkiModelUser.get_by_id(tokenEntity.user_id) # delete all user related tokens except any verify token related to account deletion that's not yet been used if tokenEntity.type == token_to_save: token_to_save = 'accountandpostsdelete' verify_tokens_to_delete = EnkiModelTokenVerify.fetch_keys_by_user_id_except_type( user_to_delete.key.id(), token_to_save) if verify_tokens_to_delete: ndb.delete_multi(verify_tokens_to_delete) email_rollback_tokens_to_delete = EnkiModelTokenEmailRollback.fetch_keys_by_user_id( user_to_delete.key.id()) if email_rollback_tokens_to_delete: ndb.delete_multi(email_rollback_tokens_to_delete) # Delete the user account and log them out. if not HandlerBase.account_is_active(user_to_delete.key.id()): # delete user if the account is inactive display_names = EnkiModelDisplayName.fetch_keys_by_user_id( user_to_delete.key.id()) if display_names: ndb.delete_multi(display_names) user_to_delete.key.delete() else: # anonymise the user if user_to_delete.email: # delete email subscriptions EnkiModelEmailSubscriptions.remove_by_email( user_to_delete.email) user_to_delete.email = None if user_to_delete.password: user_to_delete.password = None if user_to_delete.auth_ids_provider: user_to_delete.auth_ids_provider = [] user_to_delete.put() # keep all historical display_names. Add a new current display_name '[deleted]' (unless it's already been deleted) display_name = EnkiModelDisplayName.get_by_user_id_current( user_to_delete.key.id()) if display_name: if display_name.prefix != EnkiModelDisplayName.DELETED_PREFIX or display_name.suffix != EnkiModelDisplayName.DELETED_SUFFIX: EnkiModelDisplayName.set_display_name( user_to_delete.key.id(), EnkiModelDisplayName.DELETED_PREFIX, EnkiModelDisplayName.DELETED_SUFFIX) # delete user's sent and received messages EnkiModelMessage.delete_user_messages(user_to_delete.key.id()) # delete user's posts if required if delete_posts: EnkiModelPost.delete_user_posts(user_to_delete.key.id()) # log the deleted user out if self.enki_user == user_to_delete.key.id(): self.log_out() EnkiModelTokenAuth.revoke_user_authentications(user_to_delete.key.id())
def get_post_data(post_selected): # get a post forums_url = enki.libutil.get_local_url('forums') post = EnkiModelPost.get_by_id(int(post_selected)) post_page = enki.libutil.get_local_url('post', {'post': str(post.key.id())}) thread = EnkiModelThread.get_by_id(post.thread) thread_url = enki.libutil.get_local_url('thread', {'thread': str(thread.key.id())}) forum = EnkiModelForum.get_by_id(thread.forum) forum_url = enki.libutil.get_local_url('forum', {'forum': str(forum.key.id())}) author_data = enki.libdisplayname.get_user_id_display_name_url( enki.libdisplayname.get_EnkiUserDisplayName_by_user_id_current( post.author)) post_data = postData( forums_url, forum, forum_url, thread, thread_url, post, post_page, author_data, markdown2.markdown, ) return post_data
def add_post( user_id, thread, post_body ): result = enki.libutil.ENKILIB_OK if user_id and thread and post_body: if len( post_body ) <= POST_LENGTH_MAX: post = EnkiModelPost( author = user_id, thread = int( thread ), body = post_body ) post.put() thread_selected = ndb.Key( EnkiModelThread, int( thread )).get() thread_selected.num_posts += 1 thread_selected.put() forum_selected = ndb.Key( EnkiModelForum, thread_selected.forum ).get() forum_selected.num_posts += 1 forum_selected.put() else: result = ERROR_POST_LENGTH else: result = ERROR_POST_CREATION return result
def add_thread_and_post( user_id, forum, thread_title, post_body ): result = enki.libutil.ENKILIB_OK if user_id and forum and thread_title and post_body: if len( thread_title ) <= THREAD_TITLE_LENGTH_MAX and len( post_body ) <= POST_LENGTH_MAX: if enki.libdisplayname.get_EnkiUserDisplayName_by_user_id_current( user_id ): thread = EnkiModelThread( author = user_id, forum = int( forum ), title = thread_title, num_posts = 1 ) thread.put() post = EnkiModelPost( author = user_id, body = post_body, thread = thread.key.id()) post.put() forum_selected = ndb.Key( EnkiModelForum, int( forum )).get() forum_selected.num_posts += 1 forum_selected.num_threads += 1 forum_selected.put() else: result = ERROR_POST_CREATION else: result = ERROR_POST_LENGTH else: result = ERROR_POST_CREATION return result
def add_post(user_id, thread, post_body): result = enki.libutil.ENKILIB_OK if user_id and thread and post_body: if len(post_body) <= POST_LENGTH_MAX: post = EnkiModelPost(author=user_id, thread=int(thread), body=post_body) post.put() thread_selected = ndb.Key(EnkiModelThread, int(thread)).get() thread_selected.num_posts += 1 thread_selected.put() forum_selected = ndb.Key(EnkiModelForum, thread_selected.forum).get() forum_selected.num_posts += 1 forum_selected.put() else: result = ERROR_POST_LENGTH else: result = ERROR_POST_CREATION return result
def delete_post(user_id, post_id): thread = '' result = enki.libutil.ENKILIB_OK if user_id and post_id: post = EnkiModelPost.get_by_id(int(post_id)) if post: post.body = POST_DELETED thread = str(post.thread) post.put() else: result = ERROR_POST_DELETION return result, thread
def get_data( self, handler ): useridnumber = handler.request.route_kwargs.get( 'useridnumber' ) data = {} data[ 'posts' ] = '' data[ 'is_author' ] = False if handler.ensure_is_logged_in(): if useridnumber.isdigit() and EnkiModelUser.get_by_id( int( useridnumber ) ): posts = EnkiModelPost.get_author_posts( useridnumber ) if posts: data[ 'posts' ] = posts data[ 'is_author' ] = True if handler.user_id == posts.author_data.user_id else False return data
def delete_post( user_id, post_id ): thread = '' result = enki.libutil.ENKILIB_OK if user_id and post_id: post = EnkiModelPost.get_by_id( int( post_id )) if post: post.body = POST_DELETED thread = str( post.thread ) post.put() else: result = ERROR_POST_DELETION return result, thread
def get_post_data ( post_selected ): # get a post forums_url = enki.libutil.get_local_url( 'forums' ) post = EnkiModelPost.get_by_id( int( post_selected )) post_page = enki.libutil.get_local_url( 'post', { 'post': str( post.key.id( ) ) } ) thread = EnkiModelThread.get_by_id( post.thread ) thread_url = enki.libutil.get_local_url( 'thread', { 'thread': str( thread.key.id( ) ) } ) forum = EnkiModelForum.get_by_id( thread.forum ) forum_url = enki.libutil.get_local_url( 'forum', { 'forum': str( forum.key.id( ) ) } ) author_data = enki.libdisplayname.get_user_id_display_name_url( enki.libdisplayname.get_EnkiUserDisplayName_by_user_id_current( post.author ) ) post_data = postData( forums_url, forum, forum_url, thread, thread_url, post, post_page, author_data, markdown2.markdown, ) return post_data
def get( self, thread ): data = '' pagination = '' not_found = '' post_requested = str( self.request.get( 'start' )) post_count = str( self.request.get( 'count' )) validation_result = EnkiModelThread.validate_thread_pagination( thread, post_requested, post_count ) if validation_result == enki.libutil.ENKILIB_OK: if not post_requested: post_requested = EnkiModelPost.POST_DEFAULT if not post_count: post_count = EnkiModelPost.POSTS_PER_PAGE data = EnkiModelPost.get_thread_data( thread, post_requested, post_count ) pagination = EnkiModelPost.get_thread_pagination_data( thread, post_requested, post_count ) else: not_found = MSG.POST_THREAD_NOT_EXIST( ) self.render_tmpl( 'thread.html', False, active_menu = 'forums', data = data, pagination = pagination, user_id = self.user_id, not_found = not_found, maxpostlength = EnkiModelPost.POST_LENGTH_MAX )
def edit_post( user_id, post_id, post_body ): thread = '' result = enki.libutil.ENKILIB_OK if user_id and post_id and post_body: if len( post_body ) <= POST_LENGTH_MAX: post = EnkiModelPost.get_by_id( int( post_id )) if post: post.body = post_body thread = str( post.thread ) post.put() else: result = ERROR_POST_LENGTH else: result = ERROR_POST_EDITION return result, thread
def edit_post(user_id, post_id, post_body): thread = '' result = enki.libutil.ENKILIB_OK if user_id and post_id and post_body: if len(post_body) <= POST_LENGTH_MAX: post = EnkiModelPost.get_by_id(int(post_id)) if post: post.body = post_body thread = str(post.thread) post.put() else: result = ERROR_POST_LENGTH else: result = ERROR_POST_EDITION return result, thread
def account_is_active(cls, user_id): # detect activity on a user account result = False has_friends = True if EnkiModelFriends.fetch_by_user_id( user_id) else False has_messages = True if EnkiModelMessage.exist_sent_or_received( user_id) else False has_forum_posts = True if EnkiModelPost.fetch_by_author( user_id) else False has_product = True if EnkiModelProductKey.exist_by_purchaser_or_activator( user_id) else False has_email_subscriptions = False email = ndb.Key(EnkiModelUser, user_id).get().email if email: has_email_subscriptions = True if EnkiModelEmailSubscriptions.exist_by_email( email) else False if has_friends or has_messages or has_forum_posts or has_product or has_email_subscriptions: result = True return result
def fetch_EnkiPost_by_author(author): list = EnkiModelPost.query(EnkiModelPost.author == author).order( -EnkiModelPost.time_created).fetch() return list
def fetch_EnkiPost_key_by_author( author ): list = EnkiModelPost.query( EnkiModelPost.author == author ).fetch( keys_only = True ) return list
def fetch_EnkiPost_by_author( author ): list = EnkiModelPost.query( EnkiModelPost.author == author ).order( -EnkiModelPost.time_created ).fetch() return list
def fetch_EnkiPost_by_thread( thread, limit, offset ): list = EnkiModelPost.query( EnkiModelPost.thread == thread ).order( EnkiModelPost.time_created ).fetch( limit = limit, offset = offset ) return list
def post( self, post ): if self.ensure_is_logged_in() and self.ensure_has_display_name(): if post.isdigit() and EnkiModelPost.get_by_id( int( post )): data = EnkiModelPost.get_post_data( post ) is_author = True if self.user_id == data.author_data.user_id else False user = self.user_id post_body = self.request.get( 'post_body' ) submit_type = self.request.get( 'submittype' ) change = self.request.get( 'change' ) error_message = '' preview = '' if submit_type == 'delete': self.check_CSRF() result = EnkiModelPost.delete_post( user, post ) if result[ 0 ] == enki.libutil.ENKILIB_OK: self.add_infomessage( MSG.SUCCESS( ), MSG.POST_DELETED()) url = enki.libutil.get_local_url( 'thread', { 'thread' : result[ 1 ]}) self.send_email_admin( 'FPD', url ) self.redirect( url ) # redirect to parent thread return else: error_message = MSG.FAIL_POST_DELETION() elif submit_type == 'cancel': self.redirect( data.post_page ) return else: if not post_body: error_message = MSG.POST_BODY_NEEDED() else: exceed = len( post_body ) - EnkiModelPost.POST_LENGTH_MAX if exceed > 0: error_message = MSG.POST_BODY_TOO_LONG( exceed ) if not error_message: post_sticky_order = xint( self.request.get( 'sticky_order' )) if submit_type == 'submit': self.check_CSRF() result = EnkiModelPost.edit_post( user, post, post_body, post_sticky_order ) if result[ 0 ] == enki.libutil.ENKILIB_OK: self.add_infomessage( MSG.SUCCESS( ), MSG.POST_MODIFIED()) url = enki.libutil.get_local_url( 'thread', { 'thread' : result[ 1 ]}) self.send_email_admin( 'FPE', url ) self.redirect( url ) # redirect to parent thread return else: error_message = MSG.FAIL_POST_MODIFICATION() elif submit_type == 'preview': preview = post_body self.render_tmpl( 'post.html', active_menu = 'forums', data = data, change = change, isauthor = is_author, has_permission_sticky = self.has_permissions( self.enki_user, [ 'PFPS' ]), error = error_message, postbody = post_body, maxpostlength = EnkiModelPost.POST_LENGTH_MAX, preview = preview )
def post( self, forum ): if self.ensure_is_logged_in() and self.ensure_has_display_name(): if forum.isdigit() and EnkiModelForum.get_by_id( int( forum )): user_id = self.user_id thread_title = self.request.get( 'thread_title' ) post_body = self.request.get( 'post_body' ) thread_sticky_order = xint( self.request.get( 'sticky_order_thread' )) post_sticky_order = xint( self.request.get( 'sticky_order_post' )) submit_type = self.request.get( 'submittype' ) error_message_threadtitle = '' error_message_postbody = '' pmtoken = self.request.get( 'preventmultitoken' ) show_input = True if submit_type == 'cancel' or submit_type == 'input': thread_title = '' post_body = '' thread_sticky_order = 0 post_sticky_order = 0 if submit_type == 'input': pmtoken = EnkiModelTokenVerify.add_preventmultipost_token( 'preventmultipost' ) else: self.check_CSRF() if not thread_title: error_message_threadtitle = MSG.THREAD_TITLE_NEEDED( ) else: exceed = len( thread_title ) - EnkiModelThread.THREAD_TITLE_LENGTH_MAX if exceed > 0: error_message_threadtitle = MSG.THREAD_TITLE_TOO_LONG( exceed ) if not post_body: error_message_postbody = MSG.POST_BODY_NEEDED() else: exceed = len( post_body ) - EnkiModelPost.POST_LENGTH_MAX if exceed > 0: error_message_postbody = MSG.POST_BODY_TOO_LONG( exceed ) if not error_message_threadtitle and not error_message_postbody: if submit_type == 'submit': if EnkiModelTokenVerify.check_and_delete_preventmultipost_token( pmtoken, 'preventmultipost' ): result = EnkiModelPost.add_thread_and_post( user_id, forum, thread_title, thread_sticky_order, post_body, post_sticky_order ) if result == enki.libutil.ENKILIB_OK: self.add_infomessage( MSG.SUCCESS( ), MSG.THREAD_PUBLISHED()) url = enki.libutil.get_local_url( 'forum', { 'forum':forum }) self.send_email_admin( 'FTPA', url ) self.redirect( url ) return else: error_threadtitle = MSG.FAIL_THREAD_SUBMISSION() else: thread_title = '' post_body = '' self.render_tmpl( 'forum.html', CSRFneeded = show_input, active_menu = 'forums', data = EnkiModelThread.get_forum_data( forum ), has_permission_sticky = self.has_permissions( self.enki_user, [ 'PFPS', 'PFTS' ]), show_input = show_input, preventmultitoken = pmtoken, error_threadtitle = error_message_threadtitle, error_postbody = error_message_postbody, maxpostlength = EnkiModelPost.POST_LENGTH_MAX, maxthreadtitlelength = EnkiModelThread.THREAD_TITLE_LENGTH_MAX, threadtitle = thread_title, postbody = post_body, threadstickyorder = thread_sticky_order, poststickyorder = post_sticky_order, preview = True if ( submit_type == 'preview' and thread_title and post_body ) else False)
def fetch_EnkiPost_by_thread(thread, limit, offset): list = EnkiModelPost.query(EnkiModelPost.thread == thread).order( EnkiModelPost.time_created).fetch(limit=limit, offset=offset) return list
def fetch_EnkiPost_key_by_author(author): list = EnkiModelPost.query(EnkiModelPost.author == author).fetch( keys_only=True) return list
def post( self, thread ): if self.ensure_is_logged_in() and self.ensure_has_display_name(): if thread.isdigit() and EnkiModelThread.get_by_id( int( thread )): user = self.user_id post_body = self.request.get( 'post_body' ) submit_type = self.request.get( 'submittype' ) post_count = str( self.request.get( 'count' )) post_requested = str( self.request.get( 'start' )) if not post_count: post_count = EnkiModelPost.POSTS_PER_PAGE if not post_requested: post_requested = EnkiModelPost.get_first_post_on_page( EnkiModelPost.get_page( EnkiModelThread.get_by_id( int( thread )), EnkiModelPost.POST_LAST, int( post_count )), int( post_count )) error_message = '' preview = '' pmtoken = self.request.get( 'preventmultitoken' ) show_input = True if submit_type == 'input': post_body = '' pmtoken = EnkiModelTokenVerify.add_preventmultipost_token( 'preventmultipost' ) else: self.check_CSRF() if submit_type != 'cancel': if not post_body: error_message = MSG.POST_BODY_NEEDED() else: exceed = len( post_body ) - EnkiModelPost.POST_LENGTH_MAX if exceed > 0: error_message = MSG.POST_BODY_TOO_LONG( exceed ) if not error_message: post_sticky_order = xint( self.request.get( 'sticky_order' )) if submit_type == 'submit': if EnkiModelTokenVerify.check_and_delete_preventmultipost_token( pmtoken, 'preventmultipost' ): result = EnkiModelPost.add_post( user, thread, post_body, post_sticky_order ) if result == enki.libutil.ENKILIB_OK: self.add_infomessage( MSG.SUCCESS( ), MSG.POST_PUBLISHED()) post_requested = EnkiModelPost.get_first_post_on_page( EnkiModelPost.get_page( EnkiModelThread.get_by_id( int( thread )), EnkiModelPost.POST_LAST, int( post_count )), int( post_count )) url = enki.libutil.get_local_url( 'thread', { 'thread': thread, 'start': str( post_requested ), 'count': str( post_count )}) self.send_email_admin( 'FPA', url ) self.redirect( url ) return else: error_message = MSG.FAIL_POST_SUBMISSION() else: post_body = '' elif submit_type == 'preview': preview = post_body elif submit_type == 'cancel': post_body = '' data = EnkiModelPost.get_thread_data( thread, post_requested, post_count ) pagination = EnkiModelPost.get_thread_pagination_data( thread, post_requested, post_count ) self.render_tmpl( 'thread.html', CSRFneeded = show_input, active_menu = 'forums', data = data, pagination = pagination, user_id = self.user_id, has_permission_sticky = self.has_permissions( self.enki_user, [ 'PFPS' ]), show_input = show_input, preventmultitoken = pmtoken, error = error_message, maxpostlength = EnkiModelPost.POST_LENGTH_MAX, postbody = post_body, preview = preview )