Example #1
0
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')
Example #2
0
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')
Example #3
0
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')
Example #4
0
    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})
Example #5
0
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}')
Example #6
0
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
Example #7
0
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
Example #8
0
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
Example #9
0
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
Example #10
0
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
Example #11
0
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
Example #12
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)
Example #13
0
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)
Example #14
0
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)