def log_request(code, params, exception, method, status, app=None, user=None, ip=None, class_name=None, action_name=None): ''' Add an entry to user request log @param settings base Measurement base, accepts 2 or 10. defaults to 2. unit The unit of the measurement, e.g., B, Bytes/s, bps, etc. @param code message code (ending with L) for the request made by user @param params templating parameters for the message referred by code @param exception None if no exception, or a dict containing code error message code (ending with E, I or W) params templating parameters for the message referred by code @param method the string corresponding to HTTP method (GET, PUT, POST, DELETE) or the string 'TASK', meaning a log entry to track completion of an asynchronous task. 'TASK' log entries are not visible to user. @param status HTTP request status code @param app the root URI of the mounted cherrypy application. Defaults to cherrypy request application @param user the logged in user that made the request. Defaults to cherrypy request user @param ip the IP address of the user that made the request. Defaults to cherrypy request remote IP address @returns ID of log entry ''' if app is None: app = cherrypy.request.app.script_name if user is None: user = cherrypy.session.get(USER_NAME, 'N/A') or 'N/A' if ip is None: ip = cherrypy.request.remote.ip log_id = RequestRecord({ 'code': code, 'params': params }, exception, app=app, req=method, status=status, user=user, ip=ip).log() if class_name: send_wok_notification(app, class_name, method, action_name) send_wok_notification('', 'logs', 'POST') return log_id
def del_notification(code): global notificationsStore try: del notificationsStore[str(code)] except Exception as e: raise OperationFailed("WOKNOT0002E", {'id': str(code), 'msg': e.msg()}) send_wok_notification('', 'notification', 'DELETE')
def logout(self): method = 'POST' code = self.getRequestMessage(method, 'logout') params = {'username': cherrypy.session.get(auth.USER_NAME, 'N/A')} auth.logout() send_wok_notification('', 'logout', 'POST') log_request(code, params, None, method, 200, user=params['username']) return '{}'
def add_notification(code, args=None, plugin_name=None): if args is None: args = {} if not code: wok_log.error("Unable to add notification: invalid code '%(code)s'" % {'code': str(code)}) return global notificationsStore notification = notificationsStore.get(code) # do not update timestamp if notification already exists timestamp = datetime.now().isoformat() if notification is None else \ notification['timestamp'] args.update({"_plugin_name": plugin_name, "timestamp": timestamp}) notificationsStore[code] = args send_wok_notification('', 'notifications', 'POST')
def _events_handler(self, conn, pool, ev, details, opaque): # Do not use any known method (POST, PUT, DELETE) as it is used by Wok # engine and may lead in having 2 notifications for the same action send_wok_notification('/plugins/kimchi', opaque, 'METHOD')
if (time.time() - self.failed_logins[user_ip_sid]["time"]) < 30: self.failed_logins[user_ip_sid]["time"] = time.time() self.failed_logins[user_ip_sid]["count"] += 1 # more than 3 fails: raise error if self.failed_logins[user_ip_sid]["count"] >= 3: _raise_timeout(user_ip_sid) # return same error message to frontend details = e = OperationFailed("WOKAUTH0008E") status = e.getHttpStatusCode() raise cherrypy.HTTPError(401, e.message) finally: send_wok_notification('', 'login', 'POST') log_request(code, params, details, method, status) return json.dumps(user_info) @cherrypy.expose def logout(self): method = 'POST' code = self.getRequestMessage(method, 'logout') params = {'username': cherrypy.session.get(auth.USER_NAME, 'N/A')} auth.logout() send_wok_notification('', 'logout', 'POST') log_request(code, params, None, method, 200, user=params['username'])
def login(self, *args): def _raise_timeout(user_id): length = self.failed_logins[user_ip_sid]['count'] timeout = (length - 2) * 30 details = e = UnauthorizedError( 'WOKAUTH0004E', {'seconds': timeout}) log_request(code, params, details, method, 403) raise cherrypy.HTTPError(403, str(e)) details = None method = 'POST' code = self.getRequestMessage(method, 'login') try: params = parse_request() validate_params(params, self, 'login') username = params['username'] password = params['password'] except WokException as e: details = e = OperationFailed('WOKAUTH0007E') log_request(code, params, details, method, 400) raise cherrypy.HTTPError(400, str(e)) # get authentication info remote_ip = cherrypy.request.remote.ip session_id = str(cherrypy.session.originalid) user_ip_sid = re.escape(username + remote_ip + session_id) # check for repetly count = self.failed_logins.get(user_ip_sid, {'count': 0}).get('count') if count >= 3: # verify if timeout is still valid last_try = self.failed_logins[user_ip_sid]['time'] if time.time() < (last_try + ((count - 2) * 30)): _raise_timeout(user_ip_sid) else: self.failed_logins.pop(user_ip_sid) try: status = 200 user_info = auth.login(username, password) # user logged sucessfuly: reset counters if self.failed_logins.get(user_ip_sid) is not None: self.failed_logins.pop(user_ip_sid) except cherrypy.HTTPError as e: # store time and prevent too much tries if self.failed_logins.get(user_ip_sid) is None: self.failed_logins[user_ip_sid] = { 'time': time.time(), 'ip': remote_ip, 'session_id': session_id, 'username': username, 'count': 1, } else: # tries take more than 30 seconds between each one: do not # increase count if time.time() - self.failed_logins[user_ip_sid]['time'] < 30: self.failed_logins[user_ip_sid]['time'] = time.time() self.failed_logins[user_ip_sid]['count'] += 1 # more than 3 fails: raise error if self.failed_logins[user_ip_sid]['count'] >= 3: _raise_timeout(user_ip_sid) # return same error message to frontend details = e = OperationFailed('WOKAUTH0008E') status = e.getHttpStatusCode() raise cherrypy.HTTPError(401, str(e)) finally: send_wok_notification('', 'login', 'POST') log_request(code, params, details, method, status) return json.dumps(user_info)