Пример #1
0
def note():
    """Search or create note(s).

    GET /api/note
    Query parameters:
    begin - PATE timestamp (Unix timestamp)
    end - PATE timestamp (Unix timestamp)
    API responds with 200 OK and:
    {
        ...,
        "data" : [
            {
                "id"            : (int),
                "session_id"    : (int),
                "text"          : (str),
                "created"       : (int)
            },
            ...
        ],
        ...
    }

    POST /api/note
    No query parameters supported.
    Required payload:
    {
        "text" : (str)
    }
    API will respond with 200 OK and:
    {
        ...,
        "data" : {
            id" : (int)
        },
        ...
    }
    """
    log_request(request)
    try:
        from api.Note import Note
        note = Note(request)
        if request.method == 'POST':
            return api.response(note.create())
        elif request.method == 'GET':
            return api.response(note.search())
        else:
            # Should be impossible
            raise api.MethodNotAllowed(
                "'{}' method not allowed for '{}'".format(
                    request.method, request.url_rule))
    except Exception as e:
        return api.exception_response(e)
Пример #2
0
def api_file_id(id):
    """Database table row endpoint. Retrieve (GET) or update (PUT) record."""
    log_request(request)
    try:
        if request.method == 'PUT':
            return api.response(api.File().update(id, request, sso.uid))
        elif request.method == 'GET':
            return api.response(api.File().fetch(id))
        else:
            raise api.MethodNotAllowed(
                f"Method {request.method} not supported for this endpoint.")
    except Exception as e:
        return api.exception_response(e)
Пример #3
0
def psu():
    """Read PSU values.

    GET /api/psu
    No query parameters supported.
    API returns 200 OK and:
    {
        ...,
        "data" : {
            "power"             : ("OFF" | "ON"),
            "state"             : ("OK" | "OVER CURRENT"),
            "measured_current"  : (float),
            "measured_voltage"  : (float),
            "voltage_setting"   : (float),
            "current_limit"     : (float),
            "modified"          : (int)
        },
        ...
    }

    If the backend is not running, 404 Not Found is returned.
    """
    log_request(request)
    try:
        from api.PSU import PSU
        return api.response(PSU(request).get())
    except Exception as e:
        return api.exception_response(e)
Пример #4
0
def api_file_owned():
    """Return JSON listing of files owned by currently authenticated person. Slightly 'special' endpoint that accepts only GET method and no parameters of any kind. Data is returned based on the SSO session role. Specially created for Upload and Manage UI, to list user's files."""
    log_request(request)
    try:
        return api.response(api.File().search(owner=sso.uid or ''))
    except Exception as e:
        return api.exception_response(e)
Пример #5
0
def api_file(ftype=None):
    """List of downloadable file, with optional type filtering. Allowed types are "vm" and "usb".
    
    GET /api/file
    GET /api/file/usb
    GET /api/file/vm
    Query parameters:
    (none implemented)
    API returns 200 OK and:
    {
        ...,
        "data" : [
            {
                TBA
            },
            ...
        ],
        ...
    }
    """
    log_request(request)
    try:
        if ftype not in (None, "usb", "vm"):
            raise api.InvalidArgument(f"Invalid type '{ftype}'!")
        from api.File import File
        return api.response(File().search(file_type=ftype,
                                          downloadable_to=sso.role))
    except Exception as e:
        return api.exception_response(e)
Пример #6
0
def housekeeping_aggregate(function):
    """Aggregated PATE Housekeeping data

    GET /api/housekeeping/<string:function>
    Allowed aggregate functions are: avg, sum, min, max and count.
    Query parameters:
    begin - PATE timestamp (Unix timestamp)
    end - PATE timestamp (Unix timestamp)
    fields - A comma separated list of fields to return
    API returns 200 OK and:
    {
        ...,
        "data" : {
            <fields according to query parameter 'fields'>
        },
        ...
    }

    Parameters 'begin' and 'end' are integers, although the 'timestamp' field they are compared to, is a decimal number. NOTE: This datetime format is placeholder, because instrument development has not formally specified the one used in the actual satellite. Internally, Python timestamp is used.

    Unlike in the above described API endpoint, these responses do not explicitly include primary key field ('timestamp'), because that would defeat the purpose of the aggregate functions.
    """
    log_request(request)
    try:
        from api.Housekeeping import Housekeeping
        if function.lower() not in ('avg', 'sum', 'min', 'max', 'count'):
            raise api.InvalidArgument(
                "Function '{}' is not supported!".format(function))
        return api.response(Housekeeping(request).get(function))
    except Exception as e:
        return api.exception_response(e)
Пример #7
0
def api_file_schema():
    """Create data schema JSON for client FORM creation."""
    log_request(request)
    try:
        return api.response(api.File().schema())
    except Exception as e:
        return api.exception_response(e)
Пример #8
0
def hitcount_aggregate(function):
    """Aggregated classified PATE particle hits

    GET /api/hitcount/<string:function>
    Allowed aggregate functions are: avg, sum, min, max and count.
    Query parameters:
    begin - PATE timestamp (Unix timestamp)
    end - PATE timestamp (Unix timestamp)
    fields - A comma separated list of fields to return
    API returns 200 OK and:
    {
        ...,
        "data" : {
            <fields according to query parameter 'fields'>
        },
        ...
    }

    Data is logically grouped into full rotations, each identified by the timestamp when the rotation started. Information on rotational period or starting time of each sector is not available within data. It must be deciphered separately, if needed.

    Parameters 'begin' and 'end' are integers, although the 'rotation' field they are compared to, is a decimal number. NOTE: This datetime format is placeholder, because instrument development has not formally specified the one used in the actual satellite. Internally, Python timestamp is used.

    A JSON list containing a single object is returned. The identifier field ('timestamp') is never included, because that would defeat the purpose of the aggregate functions."""
    log_request(request)
    try:
        from api.HitCount import HitCount
        if function.lower() not in ('avg', 'sum', 'min', 'max', 'count'):
            raise api.InvalidArgument(
                "Function '{}' is not supported!".format(function))
        return api.response(HitCount(request).get(function))
    except Exception as e:
        return api.exception_response(e)
Пример #9
0
def housekeeping():
    """PATE Housekeeping data

    GET /api/housekeeping
    Query parameters:
    begin - PATE timestamp (Unix timestamp)
    end - PATE timestamp (Unix timestamp)
    fields - A comma separated list of fields to return
    API returns 200 OK and:
    {
        ...,
        "data" : [
            {
                <fields according to query parameter 'fields'>
            },
            ...
        ],
        ...
    }

    Parameters 'begin' and 'end' are integers, although the 'rotation' field they are compared to, is a decimal number. NOTE: This datetime format is placeholder, because instrument development has not formally specified the one used in the actual satellite. Internally, Python timestamp is used.

    A JSON list of objects is returned. Among object properties, primary key 'timestamp' is always included, regardless what 'fields' argument specifies. Data exceeding 7 days should not be requested. For more data, CSV services should be used."""
    log_request(request)
    try:
        from api.Housekeeping import Housekeeping
        return api.response(Housekeeping(request).get())
    except Exception as e:
        return api.exception_response(e)
Пример #10
0
def hitcount():
    """Classified PATE hit counters

    GET /api/hitcount
    Query parameters:
    begin - PATE timestamp (Unix timestamp)
    end - PATE timestamp (Unix timestamp)
    fields - A comma separated list of fields to return
    API returns 200 OK and:
    {
        ...,
        "data" : [
            {
                <fields according to query parameter 'fields'>
            },
            ...
        ],
        ...
    }


    Data is logically grouped into full rotations, each identified by the timestamp when the rotation started. Field/column descriptions are unavailable until they have been formally specified by instrument development.

    Parameters 'begin' and 'end' are integers, although the 'rotation' field they are compared to, is a decimal number. NOTE: This datetime format is placeholder, because instrument development has not formally specified the one used in the actual satellite. Internally, Python timestamp is used.

    A JSON list of objects is returned. Among object properties, primary key 'timestamp' is always included, regardless what 'fields' argument specifies. Data exceeding 7 days should not be requested. For more data, CSV services should be used."""
    log_request(request)
    try:
        from api.HitCount import HitCount
        return api.response(HitCount(request).get())
    except Exception as e:
        return api.exception_response(e)
Пример #11
0
def pulseheight_aggregate(function):
    """Aggregated raw PATE pulse height data.

    GET /api/pulseheight/<string:function>
    Allowed aggregate functions are: avg, sum, min, max and count.
    Query parameters:
    begin - PATE timestamp (Unix timestamp)
    end - PATE timestamp (Unix timestamp)
    fields - A comma separated list of fields to return
    API returns 200 OK and:
    {
        ...,
        "data" : [
            {
                <fields according to query parameter 'fields'>
            },
            ...
        ],
        ...
    }
    """
    log_request(request)
    try:
        from api.PulseHeight import PulseHeight
        if function.lower() not in ('avg', 'sum', 'min', 'max', 'count'):
            raise api.InvalidArgument(
                "Function '{}' is not supported!".format(function))
        return api.response(PulseHeight(request).get(function))
    except Exception as e:
        return api.exception_response(e)
Пример #12
0
def pulseheight():
    """Raw PATE pulse height data.
    
    GET /api/pulseheight
    Query parameters:
    begin - PATE timestamp (Unix timestamp)
    end - PATE timestamp (Unix timestamp)
    fields - A comma separated list of fields to return
    API returns 200 OK and:
    {
        ...,
        "data" : [
            {
                <fields according to query parameter 'fields'>
            },
            ...
        ],
        ...
    }
    """
    log_request(request)
    try:
        from api.PulseHeight import PulseHeight
        return api.response(PulseHeight(request).get())
    except Exception as e:
        return api.exception_response(e)
Пример #13
0
def handler(a):
    try:
        return response ({
            'account' : a,
            'history' : account.read(a)['history']
        })
    except FileNotFoundError:
        return ERROR('Account does not exist.')
Пример #14
0
def show_flask_config():
    """Middleware (Flask application) configuration. Sensitive entries are
    censored."""
    # Allow output only when debugging AND when the user is authenticated
    if not sso.is_authenticated or not app.debug:
        return api.response((404, {'error': 'Permission Denied'}))
    log_request(request)
    try:
        cfg = {}
        for key in app.config:
            cfg[key] = app.config[key]
        # Censor sensitive values
        for key in cfg:
            if key in ('SECRET_KEY', 'MYSQL_DATABASE_PASSWORD'):
                cfg[key] = '<CENSORED>'
        return api.response((200, cfg))
    except Exception as e:
        return api.exception_response(e)
Пример #15
0
def runsh(shell):
    proc = tornado.process.Subprocess("cd ../../ && " + shell,
                                      shell=True,
                                      stdin=tornado.process.Subprocess.STREAM,
                                      stdout=tornado.process.Subprocess.STREAM,
                                      stderr=tornado.process.Subprocess.STREAM)
    output = yield [
        proc.stdout.read_until_close(),
        proc.stderr.read_until_close()
    ]
    output = output[0].decode() + output[1].decode()

    status = proc.proc.wait()
    if status != 0:
        return api.response(False, message=output)

    data = {"output": output}
    return api.response(True, data)
Пример #16
0
    def post(self):
        cur = yield db.sp_get_transferserver()

        header = []
        for description in cur.description:
            header.append(description[0])

        data = {"header":header, "table":cur.fetchall()}
        response = api.response(True, data)
        self.write(response)
Пример #17
0
def get_challenge():
    account = request.args.get('account')

    if bad_parameter(account, re_account):
        return ERROR('The account parameter is either missing or has a bad format.')

    return response({
        'type' : 'challenge',
        'value' : create_challenge(account)
    })
Пример #18
0
def psu_power():
    """Agilent power supply remote control.

    GET /api/psu/power
    No query parameters supported.
    Response returns:
    {
        ...,
        "data" : {
            "power": ["ON", "OFF"],
            "modified": (int)
        },
        ...
    }

    POST /api/psu/power
    No query parameters supported.
    Required payload:
    {
        "power" : ("ON" | "OFF")
    }
    API will respond with 202 Accepted and:
    {
        ...,
        "data" : {
            "command_id" : (int)
        },
        ...
    }
    """

    log_request(request)
    try:
        include = ['power', 'modified']
        if request.method == 'GET':
            from api.PSU import PSU
            return api.response(PSU(request).get(include))
        else:
            from api.Command import Command
            return api.response(Command(request).post("PSU", "SET POWER"))
    except Exception as e:
        return api.exception_response(e)
Пример #19
0
def runsh(shell):
    proc = tornado.process.Subprocess(
        "eval 'source ./server.env; cd $PROJECTROOT/$PROJECTDIR;" + shell +
        "'",
        shell=True,
        stdin=tornado.process.Subprocess.STREAM,
        stdout=tornado.process.Subprocess.STREAM,
        stderr=tornado.process.Subprocess.STREAM)
    output = yield [
        proc.stdout.read_until_close(),
        proc.stderr.read_until_close()
    ]
    output = output[0].decode() + output[1].decode()

    status = proc.proc.wait()
    if status != 0:
        return api.response(False, message=output)

    data = {"output": output}
    return api.response(True, data)
Пример #20
0
def psu_voltage():
    """Read or set PSU output voltage.

    GET /api/psu/voltage
    No query parameters supported.
    Response returns:
    {
        ...,
        "data" : {
            "measured_voltage"  : (float),
            "voltage_setting"   : (float),
            "modified"          : (int)
        },
        ...
    }

    POST /api/psu/voltage
    Required payload:
    {
        "voltage" : (float)
    }
    API will respond with 202 Accepted and:
    {
        ...,
        "data" : {
            "command_id" : (int)
        },
        ...
    }
    """
    log_request(request)
    try:
        include = ['measured_voltage', 'voltage_setting', 'modified']
        if request.method == 'GET':
            from api.PSU import PSU
            return api.response(PSU(request).get(include))
        else:
            from api.Command import Command
            return api.response(Command(request).post("PSU", "SET VOLTAGE"))
    except Exception as e:
        return api.exception_response(e)
Пример #21
0
def psu_current_limit():
    """Read or Set Current Limit Value from PSU.

    GET /api/psu/current/limit
    No query parameters supported.
    Response returns:
    {
        ...,
        "data" : {
            "current_limit" : (float),
            "modified"      : (int)
        },
        ...
    }

    POST /api/psu/current/limit
    Required payload:
    {
        "current_limit" : (float)
    }
    API will respond with 202 Accepted and:
    {
        ...,
        "data" : {
            "command_id" : (int)
        },
        ...
    }
    """
    log_request(request)
    try:
        include = ['current_limit', 'modified']
        if request.method == 'GET':
            from api.PSU import PSU
            return api.response(PSU(request).get(include))
        else:
            from api.Command import Command
            return api.response(
                Command(request).post("PSU", "SET CURRENT LIMIT"))
    except Exception as e:
        return api.exception_response(e)
Пример #22
0
def note_by_id(timestamp):
    """Fetch operator note (identified by timestamp).
    
    GET /api/note/<int:timestamp>
    No query parameters supported.
    API responds with 200 OK and:
    {
        ...,
        "data" : {
            "id"            : (int),
            "session_id"    : (int),
            "text"          : (str),
            "created"       : (int)
        },
        ...
    }
    """
    log_request(request)
    try:
        from api.Note import Note
        note = Note(request)
        api.response(note.fetch(timestamp))
    except Exception as e:
        return api.exception_response(e)
Пример #23
0
def show_flask_config():
    """Middleware (Flask application) configuration. Sensitive entries are
    censored."""
    log_request(request)
    try:
        cfg = {}
        for key in app.config:
            cfg[key] = app.config[key]
        # Censor sensitive values
        for key in cfg:
            if key in ('SECRET_KEY', 'MYSQL_DATABASE_PASSWORD'):
                cfg[key] = '<CENSORED>'
        return api.response((200, cfg))
    except Exception as e:
        return api.exception_response(e)
Пример #24
0
    def post(self):
        action = self.get_argument("action", "")
        argument = self.get_argument("argument", "")

        actions = {
            "runsh": runsh,
            "gettime": gettime,
            "settime": settime,
            "update_chips": update_chips
        }
        if action in actions:
            response = yield actions[action](argument)
        else:
            response = api.response(False, message="尚未支持的命令")
        return self.write(response)
Пример #25
0
def get_token():
    account = request.args.get('account')
    challenge_response = request.args.get('challenge_response')

    if bad_parameter(account, re_account):
        return ERROR('The account parameter is either missing or has a bad format.')

    if bad_parameter(challenge_response, re_challenge):
        return ERROR('The challenge_response parameter is either missing or has a bad format.')

    if valid_challenge_response(challenge_response, account):
        return response({
            'type' : 'token',
            'value' : create_token(account)
        })

    return ERROR('The challenge response is not valid.')
Пример #26
0
def update_chips(arg):
    argstrs = arg.split(',')
    data = None
    if len(argstrs) == 2:
        result = gmhttp.do_gmcommand(
            "send_mail", {
                "rid":
                argstrs[0],
                "content":
                '{"isattach":true,"des":"尊敬的玩家,现赠送您筹码。请您在邮件后注意查收。对您造成的不便,恳请您的谅解。","awards":[{"id":1,"num":'
                + str(argstrs[1]) + '}]}'
            })
        print(type(result))
        if "success" in str(result):
            data = {"output": "操作完成!"}
        else:
            data = {"output": "操作失败!请检查rid和筹码!"}
    else:
        data = {"output": "参数错误!"}
    return api.response(True, data)
Пример #27
0
def psu_current():
    """Read PSU current.

    GET /api/psu/voltage
    No query parameters supported.
    Response returns:
    {
        ...,
        "data" : {
            "measured_current"  : (float),
            "current_limit"     : (float),
            "modified"          : (int)
        },
        ...
    }"""
    log_request(request)
    try:
        include = ['measured_current', 'current_limit', 'modified']
        from api.PSU import PSU
        return api.response(PSU(request).get(include))
    except Exception as e:
        return api.exception_response(e)
Пример #28
0
def api_publish(id=None):
    """POST with uploaded filename will trigger prepublish procedure. For .OVA files this means reading the included .OVF file for characteristics of the virtual machine. A 'file' table row is inserted and the ID will be returned in the response JSON body { 'id': <int> }."""
    try:
        # Dummy response tuple REMOVE WHEN THIS ROUTE IS COMPLETED!
        response = (200, {
            'data': {
                '.role': f'{sso.role}',
                '.is_teacher': f'{str(sso.is_teacher)}',
                '.is_student': f'{str(sso.is_student)}',
                '.is_anonymous': f'{str(sso.is_anonymous)}',
                '.is_authenticated': f'{str(sso.is_authenticated)}'
            }
        })
        raise api.NotImplemented("Sorry! Not yet implemented!")

        if not sso.is_teacher:
            raise api.Unauthorized("Teacher privileges required")
        if not app.config.get('UPLOAD_FOLDER', None):
            raise api.InternalError(
                "Configuration parameter 'UPLOAD_FOLDER' is not set!")

        if request.method == 'GET':
            file = request.args.get('file', default=None, type=str)
            folder = app.config.get('UPLOAD_FOLDER')
            if not file:
                raise api.InvalidArgument(
                    "GET Request must provide 'file' URI variable")
            # Generate JSONForm for editing
            response = api.Publish(request).preprocess(folder + "/" + file,
                                                       sso.uid)
        elif request.method == 'POST':
            pass
    except Exception as e:
        return api.exception_response(e)
    else:
        # api.response(code: int, payload: dict) -> Flask.response_class
        return api.response(response)
Пример #29
0
def usb_file():
    """List of USB disk -type downloadables (column "type" = "usb").
    
    GET /api/usb
    Query parameters:
    (none implemented)
    API returns 200 OK and:
    {
        ...,
        "data" : [
            {
                TBA
            },
            ...
        ],
        ...
    }
    """
    log_request(request)
    try:
        from api.File import File
        return api.response(File(request).search("usb"))
    except Exception as e:
        return api.exception_response(e)
Пример #30
0
import api

name, cards, actions, state = api.request()
api.response(api.first_possible(('allin', 'raise', 'bet', 'call'), actions))
Пример #31
0
def gettime(shell):
    import time
    data = {"now": time.strftime('%Y-%m-%d %X', time.localtime())}
    return api.response(True, data)
Пример #32
0
import api

print('Connecting to API...')
api.connect_as_algorithm(
  'vertical-paxos', 
  [0, 1, 2], 
  [3, 4, 5, 6, 7], 
  [8, 9, 10, 11])

print('Waiting for requests...')
request = api.wait_for_request()

print('Got request...')
print(str(request))

print('Sending a dummy algorithmic step message...')
# A proposal is sent from process 0 -> process 1
api.propose(0, 0, 1, 0, request['id'], request['cid'], request['value'])
api.propose(1, 0, 1, 0, request['id'], request['cid'], request['value'])

# An accept is sent from process 1 -> process 0
api.accept(1, 1, 0, 0, request['id'], request['cid'], request['value'])
api.accept(0, 1, 0, 0, request['id'], request['cid'], request['value'])

print('Sending response...')
api.response(request['id'], request['cid'], request['value'])
Пример #33
0
import random
import api

name, cards, actions, state = api.request()
api.response(random.choice(actions))
Пример #34
0
import api

name, cards, actions, state = api.request()
api.response(
    api.first_possible(
        ('allin', 'raise', 'bet', 'call'),
        actions
    )
)
Пример #35
0
import api

name, cards, actions, state = api.request()
api.response('fold')
Пример #36
0
import xml.etree.ElementTree as ET
import api

name, cards, actions, state = api.request()
state = ET.parse(state)

fear = False
for act in state.getroot().findall('./betting/round/action'):
    if act.get('type') in ('raise',):
        fear = True
        break

if fear:
    api.response('fold')
else:
    api.response(
        api.first_possible(
            ('check', 'call', 'allin'),
            actions
        )
    )