def _get_dtable_metadata(dtable_uuid): access_token = get_dtable_server_token(dtable_uuid) metadata_url = DTABLE_SERVER_URL.rstrip( '/') + '/api/v1/dtables/' + dtable_uuid + '/metadata/' headers = {'Authorization': 'Token ' + access_token.decode()} response = requests.get(metadata_url, headers=headers) return response.json().get('metadata')
def is_row_in_view(row_id, view_id, dtable_uuid, table_id, dtable_server_access_token, rule_id=None, db_session=None): url = DTABLE_SERVER_URL.rstrip( '/' ) + '/api/v1/dtables/' + dtable_uuid + '/tables/' + table_id + '/is-row-in-view/' headers = { 'Authorization': 'Token ' + dtable_server_access_token.decode('utf-8') } params = { 'row_id': row_id, 'view_id': view_id, } res = requests.get(url, headers=headers, params=params) if res.status_code == 404: # perhaps 404 is reason for row_id, we only deal with 'view not found','table not found' and 'dtable not found' if not is_view_in_table(view_id, dtable_uuid, table_id, dtable_server_access_token): deal_invalid_rule(rule_id, db_session) if res.status_code != 200: logger.error(res.text) return False return json.loads(res.content).get('is_row_in_view')
def is_row_satisfy_filters(row_id, filters, filter_conjuntion, dtable_uuid, table_id, dtable_server_access_token, rule_id=None, db_session=None): url = DTABLE_SERVER_URL.rstrip( '/' ) + '/api/v1/dtables/' + dtable_uuid + '/tables/' + table_id + '/is-row-satisfy-filters/' headers = { 'Authorization': 'Token ' + dtable_server_access_token.decode('utf-8') } data = { 'row_id': row_id, 'filters': filters, 'filter_conjunction': filter_conjuntion } res = requests.get(url, headers=headers, json=data) if res.status_code == 404: deal_invalid_rule(rule_id, db_session) if res.status_code != 200: logger.error(res.text) return False return json.loads(res.content).get('is_row_satisfy_filters')
def get(self, request, workspace_id, name): # resource check workspace = Workspaces.objects.get_workspace_by_id(workspace_id) if not workspace: error_msg = "Workspace %s not found." % (workspace_id, ) return api_error(status.HTTP_404_NOT_FOUND, error_msg) dtable = DTables.objects.get_dtable(workspace, name) if not dtable: error_msg = "Table %s not found." % (name, ) return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check username = request.user.username if not check_dtable_permission(username, dtable.workspace, dtable): error_msg = "Permission denied." return api_error(status.HTTP_403_FORBIDDEN, error_msg) # checkout apps tokens = DTableAPIToken.objects.list_by_dtable(dtable) # access dtable server payload = {'admin': 'dtable', 'exp': int(time.time()) + 60 * 60 * 3} access_token = jwt.encode(payload, DTABLE_PRIVATE_KEY, algorithm='HS256').decode() headers = {'authorization': 'Token ' + access_token} app_status_url = DTABLE_SERVER_URL.strip( '/') + '/api/v1/internal/' + dtable.uuid.hex + '/connected-apps/' try: resp = requests.get(app_status_url, headers=headers) except Exception as e: logger.error('request url: %s error: %s', app_status_url, e) error_msg = 'Internal Server Error.' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if resp.status_code != 200: logger.error('request url: %s status code: %s', app_status_url, resp.status_code) error_msg = 'Internal Server Error.' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) try: connected_apps = resp.json()['connected_apps'] except Exception as e: logger.error('checkout connected apps from response error: %s', e) error_msg = "Internal Server Error" return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) app_status = [{ 'app_name': token.app_name, 'connected': token.app_name in connected_apps, 'last_access': datetime_to_isoformat_timestr(token.last_access) } for token in tokens] return Response({'api_status_list': app_status})
def send_notification(dtable_uuid, user_msg_list, dtable_server_access_token): url = DTABLE_SERVER_URL.rstrip( '/') + '/api/v1/dtables/' + dtable_uuid + '/notifications-batch/' headers = { 'Authorization': 'Token ' + dtable_server_access_token.decode('utf-8') } body = { 'user_messages': user_msg_list, } res = requests.post(url, headers=headers, json=body) if res.status_code != 200: logger.error(f'failed to send_notification {res.text}')
def list_rows_near_deadline(dtable_uuid, table_id, view_id, date_column_name, alarm_days, dtable_server_access_token, rule_id=None, db_session=None): url = DTABLE_SERVER_URL.rstrip( '/') + '/api/v1/dtables/' + dtable_uuid + '/rows/' headers = { 'Authorization': 'Token ' + dtable_server_access_token.decode('utf-8') } query_params = { 'table_id': table_id, 'view_id': view_id, 'convert_link_id': True } try: res = requests.get(url, headers=headers, params=query_params) except Exception as e: logger.error(e) return [] if res.status_code == 404: deal_invalid_rule(rule_id, db_session) if res.status_code != 200: logger.error(res.text) return [] rows = json.loads(res.content).get('rows', []) rows_near_deadline = [] for row in rows: deadline_date_date_str = row.get(date_column_name, '') if not deadline_date_date_str: continue if ' ' in deadline_date_date_str: deadline_date_date_str = deadline_date_date_str.split(' ')[0] try: deadline_date = datetime.strptime(deadline_date_date_str, '%Y-%m-%d').date() except Exception as e: # perhaps result-type of fomular column has been changed to non-date logger.warning( 'date_column_name: %s value: %s, transfer to date error: %s', date_column_name, deadline_date_date_str, e) continue now_plus_alarm_date = date.today() + timedelta(days=int(alarm_days)) if date.today() <= deadline_date <= now_plus_alarm_date: rows_near_deadline.append(row) return rows_near_deadline
def get_table_view_columns(dtable_uuid, table_id, view_id, dtable_server_access_token): url = DTABLE_SERVER_URL.rstrip( '/') + '/api/v1/dtables/' + dtable_uuid + '/columns/' headers = { 'Authorization': 'Token ' + dtable_server_access_token.decode('utf-8') } query_params = {'table_id': table_id, 'view_id': view_id} try: response = requests.get(url, params=query_params, headers=headers) columns = response.json()['columns'] except Exception as e: logger.error( 'dtable_uuid: %s, table_id: %s, view_id: %s request columns error: %s', dtable_uuid, table_id, view_id, e) return [] return columns
def is_view_in_table(view_id, dtable_uuid, table_id, dtable_server_access_token): url = DTABLE_SERVER_URL.rstrip( '/') + '/api/v1/dtables/' + dtable_uuid + '/metadata/' headers = { 'Authorization': 'Token ' + dtable_server_access_token.decode('utf-8') } res = requests.get(url, headers=headers) # dtable not found if res.status_code == 404: return False if res.status_code != 200: return True tables = json.loads(res.content).get('metadata', {}).get('tables', {}) for table in tables: if table['_id'] == table_id: for view in table['views']: if view['_id'] == view_id: return True return False
def gen_notification_msg_with_row_id(dtable_uuid, table_id, view_id, row_id, msg, dtable_server_access_token, db_session): if not msg: return msg # checkout all blanks to fill in # if no blanks, just return msg blanks = set(re.findall(r'\{([^{]*?)\}', msg)) if not blanks: return msg columns = get_table_view_columns(dtable_uuid, table_id, view_id, dtable_server_access_token) column_blanks, col_name_dict = _get_column_blanks(blanks, columns) if not column_blanks: return msg # get row of table-view-row row_url = DTABLE_SERVER_URL.rstrip( '/') + '/api/v1/dtables/{dtable_uuid}/rows/{row_id}/'.format( dtable_uuid=dtable_uuid, row_id=row_id) headers = { 'Authorization': 'Token ' + dtable_server_access_token.decode('utf-8') } params = {'table_id': table_id, 'convert_link_id': True} try: response = requests.get(row_url, params=params, headers=headers) row = response.json() except Exception as e: logger.error( 'dtable_uuid: %s, table_id: %s, row_id: %s, request row error: %s', dtable_uuid, table_id, row_id, e) return msg, {} msg = _fill_msg_blanks(dtable_uuid, msg, column_blanks, col_name_dict, row, db_session) return msg
def list_users_by_column_key(dtable_uuid, table_id, view_id, row_id, column_key, dtable_server_access_token): url = DTABLE_SERVER_URL.rstrip( '/') + '/api/v1/dtables/' + dtable_uuid + '/rows/' + row_id + '/' headers = { 'Authorization': 'Token ' + dtable_server_access_token.decode('utf-8') } params = { 'table_id': table_id, 'view_id': view_id, 'convert': False, } res = requests.get(url, headers=headers, params=params) if res.status_code != 200: logger.error(f'failed to list_users_by_column_key {res.text}') rowdict = json.loads(res.content) user_list = rowdict.get(column_key, []) if isinstance(user_list, str): return [user_list] return user_list
import time import logging import jwt import requests from django.conf import settings from seahub.settings import DTABLE_PRIVATE_KEY, DTABLE_SERVER_URL logger = logging.getLogger(__name__) DTABLE_SERVER_SYS_INFO_URL = DTABLE_SERVER_URL.rstrip('/') + getattr( settings, 'DTABLE_SERVER_INFO_API', '/api/v1/admin/sys-info') def gen_dtable_server_admin_token(username): payload = { 'exp': int(time.time()) + 86400 * 3, 'admin': username, } access_token = jwt.encode(payload, DTABLE_PRIVATE_KEY, algorithm='HS256') return access_token.decode() def get_dtable_server_info(username): infos = { "web_socket_count": 0, "operation_count_since_up": 0, "loaded_dtables_count": 0, "last_period_operations_count": 0, "app_connection_count": 0
def dtable_row_share_link_view(request, token): # resource check dtable_row_share = DTableRowShares.objects.get_dtable_row_share_by_token( token) if not dtable_row_share: return render_error(request, 'DTable row share link does not exist.') workspace_id = dtable_row_share.workspace_id workspace = Workspaces.objects.get_workspace_by_id(workspace_id) if not workspace: return render_error(request, 'Workspace does not exist.') repo_id = workspace.repo_id repo = seafile_api.get_repo(repo_id) if not repo: return render_error(request, 'Library does not exist.') dtable_uuid = dtable_row_share.dtable_uuid dtable = DTables.objects.get_dtable_by_uuid(dtable_uuid) if not dtable: return render_error(request, 'DTable %s does not exist' % dtable_uuid) # generate json web token username = request.user.username payload = { 'exp': int(time.time()) + 86400 * 3, 'dtable_uuid': dtable.uuid.hex, 'username': username, 'permission': PERMISSION_READ, } try: access_token = jwt.encode(payload, DTABLE_PRIVATE_KEY, algorithm='HS256') except Exception as e: logger.error(e) return render_error(request, _('Internal Server Error')) url_for_row = '%s/api/v1/dtables/%s/tables/%s/rows/%s/' % \ (DTABLE_SERVER_URL.strip('/'), dtable_uuid, dtable_row_share.table_id, dtable_row_share.row_id) req_for_row = requests.Request( url_for_row, headers={"Authorization": "Token %s" % access_token.decode()}) url_for_columns = '%s/api/v1/dtables/%s/tables/%s/columns/' % \ (DTABLE_SERVER_URL.strip('/'), dtable_uuid, dtable_row_share.table_id) req_for_columns = requests.Request( url_for_columns, headers={"Authorization": "Token %s" % access_token.decode()}) try: row_content = requests.urlopen(req_for_row).read().decode() columns = requests.urlopen(req_for_columns).read().decode() except Exception as e: logger.error(e) return render_error(request, _('Internal Server Error')) return_dict = { 'row_content': row_content, 'columns': columns, 'workspace_id': workspace_id, 'dtable_name': dtable.name } return render(request, 'dtable_shared_row_view_react.html', return_dict)
def dtable_form_edit(request, token): """ Permission: 1. owner 2. group member 3. shared user with `rw` permission """ # resource check form_obj = DTableForms.objects.get_form_by_token(token) if not form_obj: return render_error(request, 'Table\'s form does not exist.') workspace_id = form_obj.workspace_id workspace = Workspaces.objects.get_workspace_by_id(workspace_id) if not workspace: return render_error(request, 'Workspace does not exist.') dtable_uuid = form_obj.dtable_uuid dtable = DTables.objects.get_dtable_by_uuid(dtable_uuid) if not dtable: return render_error(request, 'Table does not exist.') # permission check username = request.user.username permission = check_dtable_permission(username, workspace, dtable) if permission != PERMISSION_READ_WRITE: return render_permission_error(request, 'Permission denied.') if not check_user_workspace_quota(workspace): return render_error(request, 'Asset quota exceeded.') # generate json web token payload = { 'exp': int(time.time()) + 60 * 5, 'dtable_uuid': dtable_uuid, 'username': "******", 'permission': permission, } try: access_token = jwt.encode(payload, DTABLE_PRIVATE_KEY, algorithm='HS256') except Exception as e: logger.error(e) return render_error(request, _('Internal Server Error')) url = '%s/api/v1/dtables/%s/metadata/' % (DTABLE_SERVER_URL.strip('/'), dtable_uuid) req = requests.Request( url, headers={"Authorization": "Token %s" % access_token.decode()}) try: dtable_metadata = requests.urlopen(req).read().decode() except Exception as e: logger.error(e) return render_error(request, _('Internal Server Error')) share_type = form_obj.share_type shared_groups = list() if share_type == SHARED_GROUPS: group_ids = DTableFormShare.objects.list_by_form(form_obj) shared_groups = [{ 'id': group_id, 'name': group_id_to_name(group_id) } for group_id in group_ids] return_dict = { 'dtable_metadata': dtable_metadata, 'dtable_name': dtable.name, 'workspace_id': workspace_id, 'form_id': form_obj.form_id, 'form_config': form_obj.form_config, 'dtable_uuid': dtable.uuid.hex, 'dtable_web_service_url': DTABLE_WEB_SERVICE_URL, 'form_token': token, 'share_type': share_type, 'shared_groups': json.dumps(shared_groups), } return render(request, 'dtable_edit_form_view_react.html', return_dict)
def dtable_form_view(request, token): # resource check form_obj = DTableForms.objects.get_form_by_token(token) if not form_obj: return render_error(request, 'Table\'s form does not exist.') workspace_id = form_obj.workspace_id workspace = Workspaces.objects.get_workspace_by_id(workspace_id) if not workspace: return render_error(request, 'Workspace does not exist.') dtable_uuid = form_obj.dtable_uuid dtable = DTables.objects.get_dtable_by_uuid(dtable_uuid) if not dtable: return render_error(request, 'Table does not exist.') # permission check if not check_form_submit_permission(request, form_obj): return render_permission_error(request, _('Permission denied.')) # asset quota check if not check_user_workspace_quota(workspace): return render_error(request, _('Asset quota exceeded.')) # generate json web token payload = { 'exp': int(time.time()) + 60 * 5, 'dtable_uuid': dtable_uuid, 'username': "******", 'permission': PERMISSION_READ, } try: access_token = jwt.encode(payload, DTABLE_PRIVATE_KEY, algorithm='HS256') except Exception as e: logger.error(e) return render_error(request, _('Internal Server Error')) url = '%s/api/v1/dtables/%s/metadata/' % (DTABLE_SERVER_URL.strip('/'), dtable_uuid) req = requests.Request( url, headers={"Authorization": "Token %s" % access_token.decode()}) try: dtable_metadata = requests.urlopen(req).read().decode() except Exception as e: logger.error(e) return render_error(request, _('Internal Server Error')) return_dict = { 'version': SEATABLE_VERSION, 'dtable_metadata': dtable_metadata, 'workspace_id': workspace_id, 'form_id': form_obj.form_id, 'form_config': form_obj.form_config, 'dtable_name': dtable.name, 'dtable_web_service_url': DTABLE_WEB_SERVICE_URL, 'form_token': token, } return render(request, 'dtable_share_form_view_react.html', return_dict)