예제 #1
0
def towers_tower_id_processes_process_id_link_post(tower_id, process_id, link,
                                                   api_key):
    """
    towers_tower_id_processes_process_id_link_post
    
    :param tower_id: Tower Id number to look under.
    :type tower_id: int
    :param process_id: Process Id number to look under.
    :type process_id: int
    :param link: 
    :type link: dict | bytes
    :param api_key: Operation Access Key
    :type api_key: str

    :rtype: None
    """
    if connexion.request.is_json:
        link = Link.from_dict(connexion.request.get_json())

    qEquipment = application_map.Equipment
    qEquipmentInfo = info_map.Equipment
    qTower = application_map.Tower
    qProcess = application_map.Process
    session = application_map.Session()

    # find the tower
    q_tower = session.query(qTower).filter(qTower.id == tower_id).one_or_none()
    if q_tower is None or q_tower.op_id != api_key.operation_id:
        error = Error('Tower `{}` not Found'.format(tower_id))
        return error, 404

    q_process = q_tower.processes.filter(
        qProcess.id == process_id).one_or_none()
    if q_process is None or q_process.id != process_id:
        error = Error('Process `{}` not Found'.format(process_id))
        return error, 404

    # testing to see if the equipment are even valid
    try:
        q_source = session.query(qEquipment).filter(
            and_(qEquipment.id == link.source,
                 qEquipment.process_id == process_id)).one()
        q_target = session.query(qEquipment).filter(
            and_(qEquipment.id == link.target,
                 qEquipment.process_id == process_id)).one()
        make_link(link.source, link.target, link.material)

    except NoResultFound:
        error = Error('Equipment to link not found.')
        return error, 400
    except InvalidLinkMaterial as e:
        return Error(message=str(e)), 400
def is_valid_permission(perm):
    '''Check if `perm` permission is in the list of valid permissions database.
    False if invalid, True if valid.
    '''
    session = application_map.Session()
    qPermission = application_map.Permission

    try:
        q_perm = session.query(qPermission).filter(
            qPermission.name == perm).one()
        return True
    except NoResultFound:
        return False
예제 #3
0
def towers_get(api_key):
    """
    towers_get
    Gets summary information for every tower the request is authenticated to see.  This includes `tower_id` number, `type_id`, fuel status, as well as what the tower is producing at the endpoints of its reaction/mining chains. 
    :param api_key: Operation Access Key
    :type api_key: str

    :rtype: List[int]
    """
    qOperation = application_map.Operation
    session = application_map.Session()
    q_operation = session.query(qOperation).filter(
        qOperation.id == api_key.operation_id).one()

    return [t.id for t in q_operation.towers], 200
예제 #4
0
	def lookup(cls, key_value):
		qKey = application_map.Key
		session = application_map.Session()
		q = session.query(qKey).filter(qKey.value == key_value)
		q_key = q.one_or_none()
		if q_key is not None:
			key= cls(
				value=q_key.value,
				operation_id=q_key.operation_id,
				permissions=[q_key.permission],
				name=q_key.name
				)
			return key
		else:
			raise KeyNotFound("Key {} was not found.".format(key_value))
예제 #5
0
def towers_tower_id_processes_process_id_get(tower_id, process_id, api_key):
    """
    towers_tower_id_processes_process_id_get
    
    :param tower_id: Tower Id number to look under.
    :type tower_id: int
    :param process_id: Process Id number to look under.
    :type process_id: int
    :param api_key: Operation Access Key
    :type api_key: str

    :rtype: Process
    """
    qProcess = application_map.Process
    qTower = application_map.Tower
    qEquipment = application_map.Equipment
    session = application_map.Session()

    # find the tower
    q_tower = session.query(qTower).filter(qTower.id == tower_id).one_or_none()
    if q_tower is None or q_tower.op_id != api_key.operation_id:
        error = Error('Tower `{}` not Found'.format(tower_id))
        return error, 404

    try:
        q_process = q_tower.processes.filter(qProcess.id == process_id).one()
        equipment = [e.id for e in q_process.equipment]

        process_tree = ProcessTree.fromId(q_process.id)
        endpoints = process_tree.production_endpoints()

        final_outputs = [
            e.resource
            for e in q_process.equipment.filter(qEquipment.id.in_(endpoints))
        ]
        # final_outputs = [e.id for e in endpoints]
        process = Process(
            id=q_process.id, equipment=equipment,
            final_outputs=final_outputs)  # not fully implemnted yet

        return process, 200

    except NoResultFound:
        error = Error('Process `{}` not Found'.format(process_id))
        return error, 404
예제 #6
0
def towers_tower_id_processes_process_id_equipment_equipment_id_delete(
        tower_id, process_id, equipment_id, api_key):
    """
    towers_tower_id_processes_process_id_equipment_equipment_id_delete
    
    :param tower_id: Tower Id number to look under.
    :type tower_id: int
    :param process_id: Process Id number to look under.
    :type process_id: int
    :param equipment_id: Id of equipment that needs fetched.
    :type equipment_id: int
    :param api_key: Operation Access Key
    :type api_key: str

    :rtype: None
    """
    qEquipment = application_map.Equipment
    qEquipmentInfo = info_map.Equipment
    qTower = application_map.Tower
    qProcess = application_map.Process
    session = application_map.Session()

    # find the tower
    q_tower = session.query(qTower).filter(qTower.id == tower_id).one_or_none()
    if q_tower is None or q_tower.op_id != api_key.operation_id:
        error = Error('Tower `{}` not Found'.format(tower_id))
        return error, 404

    # find process
    q_process = q_tower.processes.filter(
        qProcess.id == process_id).one_or_none()
    if q_process is None or q_process.id != process_id:
        error = Error('Process `{}` not Found'.format(process_id))
        return error, 404

    q_equipment = q_process.equipment.filter(
        qEquipment.id == equipment_id).one_or_none()
    if q_equipment is None or q_equipment.id != equipment_id:
        error = Error('Equipment `{}` not Found'.format(equipment_id))
        return error, 404

    session.delete(q_equipment)
    session.commit()

    return None, 200
def operation_keys_get(api_key):
    """
    operation_keys_get
    Returns `array` of operation access sub-keys that exist for this operation. 
    :param api_key: Operation Master Access Key
    :type api_key: str

    :rtype: List[Key]
    """
    qOperation = application_map.Operation
    qKey = application_map.Key

    session = application_map.Session()
    q_operation = session.query(qOperation).filter(
        qOperation.id == api_key.operation_id).one()

    keys = [Key(k.name, k.value, k.permission) for k in q_operation.keys]

    return keys, 200
def operation_delete(api_key):
    """
    operation_delete
    Deletes the operation accessed by the given master key.  Note that this invalidates the key and deletes _all_ information under the operation including api keys, towers, and thier configurations. 
    :param api_key: Operation Master Access Key
    :type api_key: str

    :rtype: None
    """
    session = application_map.Session()

    qOperation = application_map.Operation

    q_operation = session.query(qOperation).filter(
        qOperation.id == api_key.operation_id).one()
    session.delete(q_operation)
    session.commit()

    return None, 200
def operation_keys_sub_key_patch(sub_key, api_key, key_update):
    """
    operation_keys_sub_key_patch
    Update key_update for the given access sub-key. 
    :param sub_key: Operation Access Sub-key
    :type sub_key: str
    :param api_key: Operation Master Access Key
    :type api_key: str
    :param key_update:
    :type key_update: NewKey

    :rtype: NewKey
    """
    if connexion.request.is_json:
        key_update = Key.from_dict(connexion.request.get_json())

    qKey = application_map.Key
    session = application_map.Session()

    if not is_valid_permission(key_update.permission):
        error = Error('Bad Request: Permission {} is not valid.'.format(
            key_update.permission))
        return error, 400
    elif key_update.permission == 'master':
        error = Error('Cannot set a sub key with permission `master`.')
        return error, 400

    q_key = session.query(qKey).filter(qKey.value == sub_key).filter(
        qKey.operation_id == api_key.operation_id).one_or_none()
    key_update.value = q_key.value
    if q_key is None:
        error = Error('Key `{}` not Found'.format(sub_key))
        return error, 404

    elif q_key.permission == 'master':
        error = Error('Cannot alter Master Key')
        return error, 400

    else:
        q_key.name = q_key.name if key_update.name is None else key_update.name
        q_key.permission = q_key.permission if key_update.permission is None else key_update.permission
        session.commit()
        return key_update, 200
def operation_post(operation_name=None):
    """
    operation_post
    Creates a new operation and returns operation details (including the `master key`). Optional parameters include the private name and public name of the operation.  These can be changed later. 
    :param operation_name: Operation Name and Public Name
    :type operation_name: dict | bytes

    :rtype: Operation
    """
    if connexion.request.is_json:
        operation_name = OperationName.from_dict(connexion.request.get_json())

    name = operation_name.name or "default operation"
    public_name = operation_name.public_name or "default operation - public"

    key_value = uuid.uuid4().hex

    qKey = application_map.Key
    qOperation = application_map.Operation
    session = application_map.Session()

    q_operation = qOperation(name=name, public_name=public_name)

    q_operation.master_key = qKey(value=key_value,
                                  permission='master',
                                  name='Master Key')

    operation = Operation(master_key=key_value,
                          name=name,
                          public_name=public_name,
                          tower_count=0,
                          sub_key_count=1)

    session.add(q_operation)
    session.commit()

    # let sqlite decide what the operation id should be, then make sure they match
    q_operation.master_key.operation_id = q_operation.id
    session.commit()

    return operation, 200
예제 #11
0
def towers_post(tower_details, api_key):
    """
    towers_post
    Add new tower. 
    :param tower_details: New tower information in json format.
    :type tower_details: dict | bytes
    :param api_key: Operation Access Key
    :type api_key: str

    :rtype: TowerDetails
    """
    if connexion.request.is_json:
        tower_details = TowerDetails.from_dict(connexion.request.get_json())

    if tower_details.fuel_last_update is None:
        tower_details.fuel_last_update = int(time.time())

    qTower = application_map.Tower
    session = application_map.Session()
    newTower = qTower(op_id=api_key.operation_id,
                      type=tower_details.type,
                      name=tower_details.name,
                      system=tower_details.system,
                      planet=tower_details.planet,
                      moon=tower_details.moon,
                      cycles_at=tower_details.cycles_at,
                      stront_count=tower_details.stront_count,
                      fuel_count=tower_details.fuel_count,
                      fuel_last_update=tower_details.fuel_last_update,
                      online=tower_details.online,
                      sov=tower_details.sov)

    session.add(newTower)
    session.commit()
    newTower.id += random.randint(
        0, 999)  # add some uncertainty so that id is not directly tower count
    tower_details.id = newTower.id

    session.commit()

    return tower_details, 200
예제 #12
0
def make_link(source_id, target_id, material_id):
    '''make_link(source_id, target_id, material_id)

    creates a link entry with the given parameters.

    if either the source or target equipment does not produce/consume 
    the material_id, returns a InvalidLinkMaterial exception.  If a material
    link slot is already occupied on either end of the equipment, the old link
    is replaced with the new one.  This happens silently.
    '''
    qLink = application_map.Link
    qEquipment = application_map.Equipment
    session = application_map.Session()

    source_linkable = available_links(source_id)
    target_linkable = available_links(target_id, outputs=False)

    if material_id in source_linkable and material_id in target_linkable:
        # see if this material has been linked to/from either source or target equipment
        q_link = session.query(qLink).filter(
            and_(qLink.resource == material_id,
                 or_(qLink.source == source_id,
                     qLink.target == target_id))).one_or_none()
        if q_link is None:
            # link does not exist, make a new one
            q_link = qLink(source=source_id,
                           target=target_id,
                           resource=material_id)
            session.add(q_link)
        else:
            # the material was linked already, just modify the old link
            q_link.source = source_id
            q_link.target = target_id

        session.commit()

    else:
        raise InvalidLinkMaterial(
            'Not a valid Link Material (must be both an output at source and input at target).'
        )
예제 #13
0
def towers_tower_id_delete(tower_id, api_key):
    """
    towers_tower_id_delete
    Delete a specific tower and all its equipment/processes. 
    :param tower_id: Id number of the tower to be deleted.
    :type tower_id: int
    :param api_key: Operation Access Key
    :type api_key: str

    :rtype: None
    """
    qTower = application_map.Tower
    session = application_map.Session()

    q_tower = session.query(qTower).filter(qTower.id == tower_id).one_or_none()
    if q_tower is None or q_tower.op_id != api_key.operation_id:
        error = Error('Tower `{}` not Found'.format(tower_id))
        return error, 404
    else:
        session.delete(q_tower)
        session.commit()
    return None, 200
def operation_keys_sub_key_get(sub_key, api_key):
    """
    operation_keys_sub_key_get
    Gets the permission settings of the given access key. 
    :param sub_key: Operation Access Sub-key
    :type sub_key: str
    :param api_key: Operation Master Access Key
    :type api_key: str

    :rtype: Key
    """
    qKey = application_map.Key
    session = application_map.Session()
    q_key = session.query(qKey).filter(qKey.value == sub_key).filter(
        qKey.operation_id == api_key.operation_id).one_or_none()
    if q_key is None:
        error = Error('Key `{}` not Found'.format(sub_key))
        return error, 404
    else:
        key = Key(name=q_key.name,
                  value=q_key.value,
                  permission=q_key.permission)
        return key, 200
예제 #15
0
def towers_tower_id_get(tower_id, api_key):
    """
    towers_tower_id_get
    Gets details for a specific tower with `type_id`. 
    :param tower_id: Type of the item that needs fetched.
    :type tower_id: int
    :param api_key: Operation Access Key
    :type api_key: str

    :rtype: TowerDetails
    """

    qTower = application_map.Tower
    session = application_map.Session()

    # find the tower
    q_tower = session.query(qTower).filter(qTower.id == tower_id).one_or_none()
    if q_tower is None or q_tower.op_id != api_key.operation_id:
        error = Error('Tower `{}` not Found'.format(tower_id))
        return error, 404
    else:
        tower_details = TowerDetails(
            id=q_tower.id,
            type=q_tower.type,
            system=q_tower.system,
            planet=q_tower.planet,
            moon=q_tower.moon,
            name=q_tower.name,
            cycles_at=q_tower.cycles_at,
            stront_count=q_tower.stront_count,
            fuel_count=q_tower.fuel_count,
            fuel_last_update=q_tower.fuel_last_update,
            online=q_tower.online,
            sov=q_tower.sov,
            processes=[p.id for p in q_tower.processes])

        return tower_details, 200
def operation_get(api_key):
    """
    operation_get
    Gets general information about the operation accessed by the given master key. 
    :param api_key: Operation Master Access Key
    :type api_key: str

    :rtype: Operation
    """
    session = application_map.Session()
    qOperation = application_map.Operation
    qKey = application_map.Key

    q_operation = session.query(qOperation).filter(
        qOperation.id == api_key.operation_id).one()
    master_key = q_operation.master_key

    operation = Operation(master_key=master_key.value,
                          name=q_operation.name,
                          public_name=q_operation.public_name,
                          tower_count=len(q_operation.towers),
                          sub_key_count=len(q_operation.keys))

    return operation, 200
예제 #17
0
def available_links(equipment_id, outputs=True):
    qEquipment = application_map.Equipment
    qEquipmentInfo = info_map.Equipment
    qMaterial = info_map.Material
    qReaction = info_map.Reaction

    session = application_map.Session()
    info_session = info_map.Session()

    q_equipment = session.query(qEquipment).filter(
        qEquipment.id == equipment_id).one()

    # special handle for mining arrays (unlike silos they have no inputs)
    mining_equipment_type = info_session.query(qEquipmentInfo).filter(
        qEquipmentInfo.name == 'Moon Harvesting Array')
    if q_equipment.type == mining_equipment_type:
        if outputs:
            return [q_equipment.resource]
        else:
            return []

    resource = q_equipment.resource
    if resource is None:
        return []
    else:
        q_reaction = info_session.query(qReaction).filter(
            qReaction.type == resource).one_or_none()
        if q_reaction is None:
            q_material = info_session.query(qMaterial).filter(
                qMaterial.type == resource).one()
            return [resource]
        else:
            if outputs:
                return [m.material_id for m in q_reaction.outputs]
            else:
                return [m.material_id for m in q_reaction.inputs]
예제 #18
0
def towers_tower_id_processes_process_id_equipment_equipment_id_patch(
        tower_id, process_id, equipment_id, equipment, api_key):
    """
    towers_tower_id_processes_process_id_equipment_equipment_id_patch
    
    :param tower_id: Tower Id number to look under.
    :type tower_id: int
    :param process_id: Process Id number to look under.
    :type process_id: int
    :param equipment_id: Id of equipment that needs fetched.
    :type equipment_id: int
    :param equipment: 
    :type equipment: dict | bytes
    :param api_key: Operation Access Key
    :type api_key: str

    :rtype: Equipment
    """
    if connexion.request.is_json:
        equipment = EquipmentUpdate.from_dict(connexion.request.get_json())

    qEquipment = application_map.Equipment
    qEquipmentInfo = info_map.Equipment
    qTower = application_map.Tower
    qProcess = application_map.Process
    session = application_map.Session()

    # find the tower
    q_tower = session.query(qTower).filter(qTower.id == tower_id).one_or_none()
    if q_tower is None or q_tower.op_id != api_key.operation_id:
        error = Error('Tower `{}` not Found'.format(tower_id))
        return error, 404
    # find process
    q_process = q_tower.processes.filter(
        qProcess.id == process_id).one_or_none()
    if q_process is None or q_process.id != process_id:
        error = Error('Process `{}` not Found'.format(process_id))
        return error, 404

    q_equipment = q_process.equipment.filter(
        qEquipment.id == equipment_id).one_or_none()
    if q_equipment is None or q_equipment.id != equipment_id:
        error = Error('Equipment `{}` not Found'.format(equipment_id))
        return error, 404

    q_equipment.name = equipment.name or q_equipment.name

    if equipment.resource != q_equipment.resource:
        if resource_allowed(q_equipment.type, equipment.resource):
            for q_link in q_equipment.links:
                session.delete(q_link)
            q_equipment.resource = equipment.resource
        else:
            return Error('Invalid resource for this equipment.'), 400

    q_equipment.contains = equipment.contains or q_equipment.resource
    q_equipment.last_updated = equipment.last_updated or q_equipment.last_updated
    q_equipment.online = equipment.online or q_equipment.online
    session.commit()
    equipment = Equipment(id=q_equipment.id,
                          type=q_equipment.type,
                          name=q_equipment.name,
                          resource=q_equipment.resource,
                          contains=q_equipment.contains,
                          last_updated=q_equipment.last_updated,
                          online=q_equipment.online,
                          inputs=[
                              Link(source=l.source, material=l.resource)
                              for l in q_equipment.inputs
                          ],
                          outputs=[
                              Link(target=l.target, material=l.resource)
                              for l in q_equipment.outputs
                          ])

    return equipment, 200
예제 #19
0
def towers_tower_id_processes_process_id_equipment_post(
        tower_id, process_id, equipment, api_key):
    """
    towers_tower_id_processes_process_id_equipment_post
    
    :param tower_id: Tower Id number to look under.
    :type tower_id: int
    :param process_id: Process Id number to look under.
    :type process_id: int
    :param equipment: 
    :type equipment: dict | bytes
    :param api_key: Operation Access Key
    :type api_key: str

    :rtype: Equipment
    """
    if connexion.request.is_json:
        equipment = Equipment.from_dict(connexion.request.get_json())

    try:
        # check if equipment type is valid and set the default name
        info_session = info_map.Session()
        qEquipmentInfo = info_map.Equipment
        default_name = info_session.query(qEquipmentInfo).filter(
            qEquipmentInfo.type == equipment.type).one().name
    except NoResultFound:
        error = Error('Equipment of type `{}` not valid.'.format(
            equipment.type))
        return error, 400

    qEquipment = application_map.Equipment

    qTower = application_map.Tower
    qProcess = application_map.Process
    session = application_map.Session()

    # find the tower
    q_tower = session.query(qTower).filter(qTower.id == tower_id).one_or_none()
    if q_tower is None or q_tower.op_id != api_key.operation_id:
        error = Error('Tower `{}` not Found'.format(tower_id))
        return error, 404

    q_process = q_tower.processes.filter(
        qProcess.id == process_id).one_or_none()
    if q_process is None or q_process.id != process_id:
        error = Error('Process `{}` not Found'.format(process_id))
        return error, 404

    # validate resource
    if equipment.resource is not None:
        try:
            if not resource_allowed(equipment.type, equipment.resource):
                error = Error(
                    'Resource `{}` not allowed in equipment of type `{}`.'.
                    format(equipment.resource, equipment.type))
                return error, 400
        except EquipmentNotFound as e:
            error = Error(message=str(e))
            return error, 400
        except ResourceNotFound as e:
            error = Error(message=str(e))
            return error, 400

    # set defaults if values not included
    equipment.name = equipment.name or default_name
    equipment.contains = equipment.contains or 0
    equipment.online = equipment.online or False
    equipment.last_updated = int(time.time())
    equipment.inputs = []
    equipment.outputs = []

    q_equipment = qEquipment(last_updated=equipment.last_updated,
                             resource=equipment.resource,
                             contains=equipment.contains,
                             type=equipment.type,
                             name=equipment.name,
                             online=equipment.online)

    q_process.equipment.append(q_equipment)
    session.commit()
    q_equipment.id += random.randint(
        0, 49)  # add some uncertainty so that id is not directly count
    equipment.id = q_equipment.id
    session.commit()

    return equipment, 200
예제 #20
0
def towers_tower_id_patch(tower_id, api_key, tower_update=None):
    """
    towers_tower_id_patch
    
    :param tower_id: Id number of the tower to be deleted.
    :type tower_id: int
    :param api_key: Operation Access Key
    :type api_key: str
    :param tower_update: Details to update tower with.
    :type tower_update: dict | bytes

    :rtype: TowerDetails
    """
    if connexion.request.is_json:
        tower_update = TowerDetails.from_dict(connexion.request.get_json())

    qTower = application_map.Tower
    session = application_map.Session()

    q_tower = session.query(qTower).filter(qTower.id == tower_id).one_or_none()
    if q_tower is None or q_tower.op_id != api_key.operation_id:
        error = Error('Tower `{}` not Found'.format(tower_id))
        return error, 404
    else:
        if tower_update.type is not None:
            q_tower.type = tower_update.type
        if tower_update.system is not None:
            q_tower.system = tower_update.system
        if tower_update.planet is not None:
            q_tower.planet = tower_update.planet
        if tower_update.moon is not None:
            q_tower.moon = tower_update.moon
        if tower_update.cycles_at is not None:
            q_tower.cycles_at = tower_update.cycles_at
        if tower_update.fuel_count is not None:
            q_tower.fuel_count = tower_update.fuel_count
        if tower_update.fuel_last_update is not None:
            q_tower.fuel_last_update = tower_update.fuel_last_update
        if tower_update.online is not None:
            q_tower.online = tower_update.online
        if tower_update.sov is not None:
            q_tower.sov = tower_update.sov
        if tower_update.name is not None:
            q_tower.name = tower_update.name
        if tower_update.stront_count is not None:
            q_tower.stront_count = tower_update.stront_count

        tower_details = TowerDetails(id=q_tower.id,
                                     type=q_tower.type,
                                     system=q_tower.system,
                                     planet=q_tower.planet,
                                     moon=q_tower.moon,
                                     name=q_tower.name,
                                     cycles_at=q_tower.cycles_at,
                                     stront_count=q_tower.stront_count,
                                     fuel_count=q_tower.fuel_count,
                                     fuel_last_update=q_tower.fuel_last_update,
                                     online=q_tower.online,
                                     sov=q_tower.sov,
                                     processes=[])

        session.commit()

        return tower_details, 200