def state_request(d, sr): mode = d.mode workspace = d.workspace workspace_id = workspace.id user = d.user # Dictionary for storing results. res_dict = {} # Shortcut variables force_sync = sr.hasFlags(sr.STATE_FORCE_SYNC) last_perms_update_version = sr.getIntParam('last_perms_update_version', 0) last_evt_ws_id = sr.getIntParam('last_evt_ws_id', 0) last_evt_user_id = sr.getIntParam('last_evt_user_id', 0) last_evt_kfs_id = sr.getIntParam('last_evt_kfs_id', 0) last_evt_chat_id = sr.getIntParam('last_evt_chat_id', 0) last_evt_vnc_id = sr.getIntParam('last_evt_vnc_id', 0) last_evt_skurl_id = sr.getIntParam('last_evt_skurl_id', 0) kfs_share_id = 0 chat_channel_id = sr.getIntParam('chat_channel_id', 0) #log.debug("state_request(): %s" % ( str(sr) ) ) #log.debug("state_request(): fsync=%s user_evt_id=%i kfs_evt_id=%i chat_evt_id=%i vnc_evt_id=%i skurl_evt_id=%i" % \ # ( force_sync, last_evt_user_id, last_evt_kfs_id, last_evt_chat_id, last_evt_vnc_id, last_evt_skurl_id ) ) # State variables moved = False iteration = 0 #OUTSTANDING HTTP REQUEST## Open the wake-up file and go to the end. #OUTSTANDING HTTP REQUEST#wakeup_file_path = ......... #OUTSTANDING HTTP REQUEST#wake_up_file = open(wakeup_file_path) #OUTSTANDING HTTP REQUEST#wake_up_file.seek(wakeup_size, os.SEEK_SET) #OUTSTANDING HTTP REQUEST#init_time = int(time.time()) # Loop until we got what we needed. while 1: iteration += 1 #log.debug("state_request(): iteration %i" % ( iteration ) ) # Get the workspace from model. ws = Workspace.get_by(id=workspace_id) if sr.hasFlags(StateRequest.STATE_WANT_WS): if (ws.evt_ws_id > last_evt_ws_id) or force_sync: # Send the workspace informations. moved = True res_dict[StateRequest.STATE_WANT_WS] = {} data = ws_state_request(ws) res_dict[StateRequest.STATE_WANT_WS]['last_evt'] = ws.evt_ws_id res_dict[StateRequest.STATE_WANT_WS]['data'] = data if sr.hasFlags(StateRequest.STATE_WANT_MEMBERS): if (ws.evt_user_id > last_evt_user_id) or force_sync: if d.perms.hasPerm('users.list'): # Send the members list. moved = True # NOTE (followup for the synchronisation note): # All users are fetched and scanned to get the real # last event ID, even in skurl mode. # This avoids double updates with the same data, that would be possible # if sending ws.evt_user_id instead (but note that this would not have been # a big problem in the users context because of the low probability of the race # and the low cost of sending the same update twice). res_dict[StateRequest.STATE_WANT_MEMBERS] = {} t_last_evt_id, data = user_state_request( workspace_id, user, mode, ws.evt_user_id) res_dict[StateRequest. STATE_WANT_MEMBERS]['last_evt'] = t_last_evt_id res_dict[StateRequest.STATE_WANT_MEMBERS]['data'] = data else: log.debug("No users list permission.") if sr.hasFlags(StateRequest.STATE_WANT_KFS): if (ws.evt_kfs_id > last_evt_kfs_id) or force_sync: if d.perms.hasPerm('kfs.list.share.%i' % (kfs_share_id)): # Send the KFS status. moved = True if ws.public and not d.is_admin: email_info = d.email_info identities = d.identities res_dict[StateRequest.STATE_WANT_KFS] = {} data = pubws_kfs_state_request(ws, email_info, identities) res_dict[StateRequest. STATE_WANT_KFS]['last_evt'] = ws.evt_kfs_id res_dict[StateRequest.STATE_WANT_KFS]['data'] = data else: kfs_dir_dict = sr.getParam('kfs_dir') kfs_dir = kfs_lib.WebKFSDirectory().from_dict( kfs_dir_dict) assert kfs_dir.workspace_id == workspace_id assert kfs_dir.share_id == kfs_share_id # NOTE (followup for the synchronisation note): # Not all nodes are fetched, and no locks are are used to wrap the multiple workspace and kfsnode tables # accesses... this means that: # - ws.evt_kfs_id is not that reliable # - there are no quick and easy alternatives # So, we use it anyways. With the current design, no changes updates are sent to the client: # all directory content is sent at every change, so problems are limited to # unnecessary updates: # - when there are changes in other share_ids # - when there are changes in other directories # - when changes occur between fetching workspace and fetching kfs nodes res_dict[StateRequest.STATE_WANT_KFS] = {} data = ws_kfs_state_request(kfs_dir) res_dict[StateRequest. STATE_WANT_KFS]['last_evt'] = ws.evt_kfs_id res_dict[StateRequest.STATE_WANT_KFS]['data'] = data else: log.debug("No KFS list permission.") if sr.hasFlags(StateRequest.STATE_WANT_CHAT): if (ws.evt_chat_id > last_evt_chat_id) or force_sync: if d.perms.hasPerm('chat.list.channel.%i' % (chat_channel_id)): # Send chat messages. moved = True # NOTE (followup for the synchronisation note): # Changes are sent to client, so all fetched messages are scanned to ensure # the last event ID sent matches the messages sent. # Issue: as not all messages from all channels are scanned, # this could result in sending empty results all the time # instead of not sending results (see the comparison with ws.evt_chat_id which can # occur whenever there are messages in other chat channels which have bigger event IDs). res_dict[StateRequest.STATE_WANT_CHAT] = {} t_last_evt_id, data = chat_state_request( workspace_id, chat_channel_id, last_evt_chat_id) res_dict[StateRequest. STATE_WANT_CHAT]['last_evt'] = t_last_evt_id res_dict[StateRequest.STATE_WANT_CHAT]['data'] = data else: log.debug("No chat list permission. Rules: %s." % (str(d.perms._rules))) if sr.hasFlags(StateRequest.STATE_WANT_VNC): if (ws.evt_vnc_id > last_evt_vnc_id) or force_sync: if d.perms.hasPerm('vnc.list'): moved = True res_dict[StateRequest.STATE_WANT_VNC] = {} mode, vnc_list = vnc_state_request(workspace_id, last_evt_vnc_id) res_dict[StateRequest. STATE_WANT_VNC]['last_evt'] = ws.evt_vnc_id res_dict[StateRequest.STATE_WANT_VNC]["list"] = vnc_list res_dict[StateRequest.STATE_WANT_VNC]["mode"] = mode else: log.debug("No shared applications list permission.") if sr.hasFlags(StateRequest.STATE_WANT_PERMS): #log.debug("Permissions rules: '%s'." % ( str(d.perms._rules) ) ) if (d.perms.update_version > last_perms_update_version) or force_sync: # Send permissions (last, in case some other module updates the permissions). moved = True res_dict[StateRequest.STATE_WANT_PERMS] = perms_state_request( d.perms) if sr.hasFlags(StateRequest.STATE_WANT_UPLOAD_STATUS): # Support for multiple uploads is quite easy by the js code sending multiple client_random_id's (in an array), # and setting the status of each file in res_dict client_random_id = sr.getIntParam('last_upload_random_id', 0) res_dict[StateRequest.STATE_WANT_UPLOAD_STATUS] = {} data = upload_status_state_request(client_random_id, workspace_id, kfs_share_id, user) res_dict[StateRequest.STATE_WANT_UPLOAD_STATUS]['data'] = data if sr.hasFlags(StateRequest.STATE_WANT_PUBWS_INFO): res_dict[StateRequest.STATE_WANT_PUBWS_INFO] = {} data = pubws_info_state_request(workspace_id, d.email_id) res_dict[StateRequest.STATE_WANT_PUBWS_INFO]['data'] = data # We're done. if moved: log.debug("state_request(): update at iteration %i." % (iteration)) break #OUTSTANDING HTTP REQUEST## TO CHECK BEFORE ENABLING!!! #OUTSTANDING HTTP REQUEST## Wait for something to happen. #OUTSTANDING HTTP REQUEST##if wait_for_event(req, init_time, wake_up_file): #OUTSTANDING HTTP REQUEST## break break # cache updated workspace ###if moved: ### sess.kws = kws #OUTSTANDING HTTP REQUEST## Close the wake-up file. #OUTSTANDING HTTP REQUEST#wake_up_file.close() #log.debug("handle_state(): res_dict='%s'" % ( str(res_dict) ) ) return res_dict
def state_request(d, sr): mode = d.mode workspace = d.workspace workspace_id = workspace.id user = d.user # Dictionary for storing results. res_dict = {} # Shortcut variables force_sync = sr.hasFlags(sr.STATE_FORCE_SYNC) last_perms_update_version = sr.getIntParam('last_perms_update_version', 0) last_evt_ws_id = sr.getIntParam('last_evt_ws_id', 0) last_evt_user_id = sr.getIntParam('last_evt_user_id', 0) last_evt_kfs_id = sr.getIntParam('last_evt_kfs_id', 0) last_evt_chat_id = sr.getIntParam('last_evt_chat_id', 0) last_evt_vnc_id = sr.getIntParam('last_evt_vnc_id', 0) last_evt_skurl_id = sr.getIntParam('last_evt_skurl_id', 0) kfs_share_id = 0 chat_channel_id = sr.getIntParam('chat_channel_id', 0) #log.debug("state_request(): %s" % ( str(sr) ) ) #log.debug("state_request(): fsync=%s user_evt_id=%i kfs_evt_id=%i chat_evt_id=%i vnc_evt_id=%i skurl_evt_id=%i" % \ # ( force_sync, last_evt_user_id, last_evt_kfs_id, last_evt_chat_id, last_evt_vnc_id, last_evt_skurl_id ) ) # State variables moved = False iteration = 0 #OUTSTANDING HTTP REQUEST## Open the wake-up file and go to the end. #OUTSTANDING HTTP REQUEST#wakeup_file_path = ......... #OUTSTANDING HTTP REQUEST#wake_up_file = open(wakeup_file_path) #OUTSTANDING HTTP REQUEST#wake_up_file.seek(wakeup_size, os.SEEK_SET) #OUTSTANDING HTTP REQUEST#init_time = int(time.time()) # Loop until we got what we needed. while 1: iteration += 1 #log.debug("state_request(): iteration %i" % ( iteration ) ) # Get the workspace from model. ws = Workspace.get_by(id=workspace_id) if sr.hasFlags(StateRequest.STATE_WANT_WS): if (ws.evt_ws_id > last_evt_ws_id) or force_sync: # Send the workspace informations. moved = True res_dict[StateRequest.STATE_WANT_WS] = {} data = ws_state_request(ws) res_dict[StateRequest.STATE_WANT_WS]['last_evt'] = ws.evt_ws_id res_dict[StateRequest.STATE_WANT_WS]['data'] = data if sr.hasFlags(StateRequest.STATE_WANT_MEMBERS): if (ws.evt_user_id > last_evt_user_id) or force_sync: if d.perms.hasPerm('users.list'): # Send the members list. moved = True # NOTE (followup for the synchronisation note): # All users are fetched and scanned to get the real # last event ID, even in skurl mode. # This avoids double updates with the same data, that would be possible # if sending ws.evt_user_id instead (but note that this would not have been # a big problem in the users context because of the low probability of the race # and the low cost of sending the same update twice). res_dict[StateRequest.STATE_WANT_MEMBERS] = {} t_last_evt_id, data = user_state_request(workspace_id, user, mode, ws.evt_user_id) res_dict[StateRequest.STATE_WANT_MEMBERS]['last_evt'] = t_last_evt_id res_dict[StateRequest.STATE_WANT_MEMBERS]['data'] = data else: log.debug("No users list permission.") if sr.hasFlags(StateRequest.STATE_WANT_KFS): if (ws.evt_kfs_id > last_evt_kfs_id) or force_sync: if d.perms.hasPerm('kfs.list.share.%i' % (kfs_share_id)): # Send the KFS status. moved = True if ws.public and not d.is_admin: email_info = d.email_info identities = d.identities res_dict[StateRequest.STATE_WANT_KFS] = {} data = pubws_kfs_state_request(ws, email_info, identities) res_dict[StateRequest.STATE_WANT_KFS]['last_evt'] = ws.evt_kfs_id res_dict[StateRequest.STATE_WANT_KFS]['data'] = data else: kfs_dir_dict = sr.getParam('kfs_dir') kfs_dir = kfs_lib.WebKFSDirectory().from_dict(kfs_dir_dict) assert kfs_dir.workspace_id == workspace_id assert kfs_dir.share_id == kfs_share_id # NOTE (followup for the synchronisation note): # Not all nodes are fetched, and no locks are are used to wrap the multiple workspace and kfsnode tables # accesses... this means that: # - ws.evt_kfs_id is not that reliable # - there are no quick and easy alternatives # So, we use it anyways. With the current design, no changes updates are sent to the client: # all directory content is sent at every change, so problems are limited to # unnecessary updates: # - when there are changes in other share_ids # - when there are changes in other directories # - when changes occur between fetching workspace and fetching kfs nodes res_dict[StateRequest.STATE_WANT_KFS] = {} data = ws_kfs_state_request(kfs_dir) res_dict[StateRequest.STATE_WANT_KFS]['last_evt'] = ws.evt_kfs_id res_dict[StateRequest.STATE_WANT_KFS]['data'] = data else: log.debug("No KFS list permission.") if sr.hasFlags(StateRequest.STATE_WANT_CHAT): if (ws.evt_chat_id > last_evt_chat_id) or force_sync: if d.perms.hasPerm('chat.list.channel.%i' % (chat_channel_id)): # Send chat messages. moved = True # NOTE (followup for the synchronisation note): # Changes are sent to client, so all fetched messages are scanned to ensure # the last event ID sent matches the messages sent. # Issue: as not all messages from all channels are scanned, # this could result in sending empty results all the time # instead of not sending results (see the comparison with ws.evt_chat_id which can # occur whenever there are messages in other chat channels which have bigger event IDs). res_dict[StateRequest.STATE_WANT_CHAT] = {} t_last_evt_id, data = chat_state_request(workspace_id, chat_channel_id, last_evt_chat_id) res_dict[StateRequest.STATE_WANT_CHAT]['last_evt'] = t_last_evt_id res_dict[StateRequest.STATE_WANT_CHAT]['data'] = data else: log.debug("No chat list permission. Rules: %s." % ( str(d.perms._rules) ) ) if sr.hasFlags(StateRequest.STATE_WANT_VNC): if (ws.evt_vnc_id > last_evt_vnc_id) or force_sync: if d.perms.hasPerm('vnc.list'): moved = True res_dict[StateRequest.STATE_WANT_VNC] = {} mode, vnc_list = vnc_state_request(workspace_id, last_evt_vnc_id) res_dict[StateRequest.STATE_WANT_VNC]['last_evt'] = ws.evt_vnc_id res_dict[StateRequest.STATE_WANT_VNC]["list"] = vnc_list res_dict[StateRequest.STATE_WANT_VNC]["mode"] = mode else: log.debug("No shared applications list permission.") if sr.hasFlags(StateRequest.STATE_WANT_PERMS): #log.debug("Permissions rules: '%s'." % ( str(d.perms._rules) ) ) if (d.perms.update_version > last_perms_update_version) or force_sync: # Send permissions (last, in case some other module updates the permissions). moved = True res_dict[StateRequest.STATE_WANT_PERMS] = perms_state_request(d.perms) if sr.hasFlags(StateRequest.STATE_WANT_UPLOAD_STATUS): # Support for multiple uploads is quite easy by the js code sending multiple client_random_id's (in an array), # and setting the status of each file in res_dict client_random_id = sr.getIntParam('last_upload_random_id', 0) res_dict[StateRequest.STATE_WANT_UPLOAD_STATUS] = {} data = upload_status_state_request(client_random_id, workspace_id, kfs_share_id, user) res_dict[StateRequest.STATE_WANT_UPLOAD_STATUS]['data'] = data if sr.hasFlags(StateRequest.STATE_WANT_PUBWS_INFO): res_dict[StateRequest.STATE_WANT_PUBWS_INFO] = {} data = pubws_info_state_request(workspace_id, d.email_id) res_dict[StateRequest.STATE_WANT_PUBWS_INFO]['data'] = data # We're done. if moved: log.debug("state_request(): update at iteration %i." % (iteration) ) break #OUTSTANDING HTTP REQUEST## TO CHECK BEFORE ENABLING!!! #OUTSTANDING HTTP REQUEST## Wait for something to happen. #OUTSTANDING HTTP REQUEST##if wait_for_event(req, init_time, wake_up_file): #OUTSTANDING HTTP REQUEST## break break # cache updated workspace ###if moved: ### sess.kws = kws #OUTSTANDING HTTP REQUEST## Close the wake-up file. #OUTSTANDING HTTP REQUEST#wake_up_file.close() #log.debug("handle_state(): res_dict='%s'" % ( str(res_dict) ) ) return res_dict
def __before__(self, action, controller, workspace_id=None, email_id=None): log.debug("Request to %s.%s, workspace_id=%s, email_id=%s, session_id=%s." % \ ( controller, action, str(workspace_id), str(email_id), str(session.id) ) ) # Detect changes in configuration. def config_has_changed(): model.new_engine() kcd_model.new_engine() detect_cached_config_change(config_has_changed, config['master_file_path']) # Get cached master configuration. c.mc = get_cached_master_config() # Initialize models in local thread. model.init_local() kcd_model.init_local() # Initialize context variables. c.perms = KWMOPermissions() c.logout_url = None c.glob_messages = [] # Prevent page caching. response.headers['Cache-Control'] = 'no-cache, must-revalidate' response.headers['Max-Age'] = '0' response.headers['Expires'] = 'Sat, 26 Jul 1997 05:00:00 GMT' # Detect global message passed in session (flash). if 'uimessage' in session: c.glob_messages.append(session['uimessage']) del session['uimessage'] session.save() # Detect global message passed in a GET variable. for var_name, callable in self.glob_msg_var_name_to_callable_map.items( ): code = request.GET.get(var_name, None) if code: callable(code=code) break if workspace_id: # Get workspace. ws = Workspace.get_by(id=workspace_id) if not ws: log.warn("Workspace %s does not exit." % (workspace_id)) abort(404) # Not reliable here! # Initialize some context variables. c.workspace = ws c.is_admin = False if 'admin' in session and session['admin'] == True: c.is_admin = True if 'user_id' in session and session['user_id']: # User is logged. c.logout_url = url('teambox_logout', workspace_id=c.workspace.id) if c.is_admin: # User is admin. c.logout_url = url('teambox_admin_logout', workspace_id=c.workspace.id) if 'initialized' in session: # Session is initialized. if not 'version' in session: # Update session. log.debug("Updating session.") from kwmo.lib.updates import update_session_v1 update_session_v1(c, session) # Save session. session.save() # Fill the permission object with the session permissions dictionary. c.perms.from_dict(session['perms']) else: # Initialize session. init_session(ws) # Detect some workspace property changes. self._check_workspace_prop(controller, action) # Detect perm_check. if ws.last_perm_check_id > session['last_perm_check_id']: session['last_perm_check_id'] = ws.last_perm_check_id session.save() self._check_perms() # Set welcome name to use in the header partial if (('user_id' in session) and ('user' in session) and session['user']): if c.is_admin: c.welcome_name = 'Administrator' elif session['user']['admin_name']: c.welcome_name = session['user']['admin_name'] elif session['user']['real_name']: c.welcome_name = session['user']['real_name'] else: c.welcome_name = session['user']['email'] # Check session expiration if set. if 'expiration_time' in session and \ not (controller == 'admin_teambox' and action == 'login'): if time.time() > session['expiration_time']: log.debug("Admin session expired.") init_session(c.workspace, reinit=True) redirect_to( url('message_show', workspace_id=c.workspace.id, warning_code='admin_sess_expired')) # Authenticate if action in self.requires_auth: if 'user_id' not in session: redirect_to( url('invite_resend_show', workspace_id=workspace_id))
def __before__(self, action, controller, workspace_id = None, email_id = None): log.debug("Request to %s.%s, workspace_id=%s, email_id=%s, session_id=%s." % \ ( controller, action, str(workspace_id), str(email_id), str(session.id) ) ) # Detect changes in configuration. def config_has_changed(): model.new_engine() kcd_model.new_engine() detect_cached_config_change(config_has_changed, config['master_file_path']) # Get cached master configuration. c.mc = get_cached_master_config() # Initialize models in local thread. model.init_local() kcd_model.init_local() # Initialize context variables. c.perms = KWMOPermissions() c.logout_url = None c.glob_messages = [] # Prevent page caching. response.headers['Cache-Control'] = 'no-cache, must-revalidate' response.headers['Max-Age'] = '0' response.headers['Expires'] = 'Sat, 26 Jul 1997 05:00:00 GMT' # Detect global message passed in session (flash). if 'uimessage' in session: c.glob_messages.append(session['uimessage']) del session['uimessage'] session.save() # Detect global message passed in a GET variable. for var_name, callable in self.glob_msg_var_name_to_callable_map.items(): code = request.GET.get(var_name, None) if code: callable(code=code) break if workspace_id: # Get workspace. ws = Workspace.get_by(id=workspace_id) if not ws: log.warn("Workspace %s does not exit." % ( workspace_id ) ) abort(404) # Not reliable here! # Initialize some context variables. c.workspace = ws c.is_admin = False if 'admin' in session and session['admin'] == True: c.is_admin = True if 'user_id' in session and session['user_id']: # User is logged. c.logout_url = url('teambox_logout', workspace_id=c.workspace.id) if c.is_admin: # User is admin. c.logout_url = url('teambox_admin_logout', workspace_id=c.workspace.id) if 'initialized' in session: # Session is initialized. if not 'version' in session: # Update session. log.debug("Updating session.") from kwmo.lib.updates import update_session_v1 update_session_v1(c, session) # Save session. session.save() # Fill the permission object with the session permissions dictionary. c.perms.from_dict(session['perms']) else: # Initialize session. init_session(ws) # Detect some workspace property changes. self._check_workspace_prop(controller, action) # Detect perm_check. if ws.last_perm_check_id > session['last_perm_check_id']: session['last_perm_check_id'] = ws.last_perm_check_id session.save() self._check_perms() # Set welcome name to use in the header partial if (('user_id' in session) and ('user' in session) and session['user']): if c.is_admin: c.welcome_name = 'Administrator' elif session['user']['admin_name']: c.welcome_name = session['user']['admin_name'] elif session['user']['real_name']: c.welcome_name = session['user']['real_name'] else: c.welcome_name = session['user']['email'] # Check session expiration if set. if 'expiration_time' in session and \ not (controller == 'admin_teambox' and action == 'login'): if time.time() > session['expiration_time']: log.debug("Admin session expired.") init_session(c.workspace, reinit=True) redirect_to(url('message_show', workspace_id=c.workspace.id, warning_code='admin_sess_expired')) # Authenticate if action in self.requires_auth: if 'user_id' not in session: redirect_to(url('invite_resend_show', workspace_id = workspace_id))