Beispiel #1
0
def auth_hash(req, verify=False):
    if not 'authNonce' in req:
        if verify:
            util.raise_not_found('authNonce: missing field in request')
        r = random.SystemRandom()
        req.authNonce = ''.join(
            r.choice(_AUTH_NONCE_CHARS) for x in range(_AUTH_NONCE_LEN))
    h = hashlib.sha256()
    h.update(
        # POSIT: ':' not part of simulationType or simulationId
        ':'.join([
            req.authNonce,
            req.simulationType,
            req.simulationId,
            cfg.auth_secret,
        ]), )
    res = 'v1:' + base64.urlsafe_b64encode(h.digest())
    if not verify:
        req.authHash = res
        return
    if res != req.authHash:
        util.raise_not_found(
            '{}: hash mismatch expected={} nonce={}',
            req.authHash,
            res,
            req.authNonce,
        )
Beispiel #2
0
def api_root(simulation_type):
    try:
        sirepo.template.assert_sim_type(simulation_type)
    except AssertionError:
        if simulation_type == 'warp':
            return http_reply.gen_redirect_for_root('warppba', code=301)
        if simulation_type == 'fete':
            return http_reply.gen_redirect_for_root('warpvnd', code=301)
        pkdlog('{}: uri not found', simulation_type)
        util.raise_not_found('Invalid simulation_type: {}', simulation_type)
    values = pkcollections.Dict()
    values.app_name = simulation_type
    return _render_root_page('index', values)
Beispiel #3
0
def open_json_file(sim_type, path=None, sid=None, fixup=True):
    """Read a db file and return result

    Args:
        sim_type (str): simulation type (app)
        path (py.path.local): where to read the file
        sid (str): simulation id

    Returns:
        dict: data

    Raises:
        CopyRedirect: if the simulation is in another user's
    """
    if not path:
        path = sim_data_file(sim_type, sid)
    if not os.path.isfile(str(path)):
        global_sid = None
        if sid:
            #TODO(robnagler) workflow should be in server.py,
            # because only valid in one case, not e.g. for opening examples
            # which are not found.
            user_copy_sid = _find_user_simulation_copy(sim_type, sid)
            if find_global_simulation(sim_type, sid):
                global_sid = sid
        if global_sid:
            raise CopyRedirect({
                'redirect': {
                    'simulationId': global_sid,
                    'userCopySimulationId': user_copy_sid,
                },
            })
        util.raise_not_found(
            '{}/{}: global simulation not found',
            sim_type,
            sid,
        )
    data = None
    try:
        with open(str(path)) as f:
            data = json_load(f)
            # ensure the simulationId matches the path
            if sid:
                data['models']['simulation']['simulationId'] = _sid_from_path(
                    path)
    except Exception as e:
        pkdlog('{}: error: {}', path, pkdexc())
        raise
    return fixup_old_data(data)[0] if fixup else data
Beispiel #4
0
def open_json_file(sim_type, path=None, sid=None, fixup=True):
    """Read a db file and return result

    Args:
        sim_type (str): simulation type (app)
        path (py.path.local): where to read the file
        sid (str): simulation id

    Returns:
        dict: data

    Raises:
        CopyRedirect: if the simulation is in another user's
    """
    if not path:
        path = sim_data_file(sim_type, sid)
    if not os.path.isfile(str(path)):
        global_sid = None
        if sid:
            #TODO(robnagler) workflow should be in server.py,
            # because only valid in one case, not e.g. for opening examples
            # which are not found.
            user_copy_sid = _find_user_simulation_copy(sim_type, sid)
            if find_global_simulation(sim_type, sid):
                global_sid = sid
        if global_sid:
            raise CopyRedirect({
                'redirect': {
                    'simulationId': global_sid,
                    'userCopySimulationId': user_copy_sid,
                },
            })
        util.raise_not_found(
            '{}/{}: global simulation not found',
            sim_type,
            sid,
        )
    data = None
    try:
        with open(str(path)) as f:
            data = json_load(f)
            # ensure the simulationId matches the path
            if sid:
                data['models']['simulation']['simulationId'] = _sid_from_path(path)
    except Exception as e:
        pkdlog('{}: error: {}', path, pkdexc())
        raise
    return fixup_old_data(data)[0] if fixup else data
Beispiel #5
0
def api_staticFile(path_info=None):
    """flask.send_from_directory for static folder.

    Uses safe_join which doesn't allow indexing, paths with '..',
    or absolute paths.

    Args:
        path_info (str): relative path to join
    Returns:
        flask.Response: flask.send_from_directory response
    """
    if not path_info:
        raise util.raise_not_found('empty path info')
    p = pkio.py_path(
        flask.safe_join(str(simulation_db.STATIC_FOLDER), path_info))
    r = None
    if _google_tag_manager and re.match(r'^en/[^/]+html$', path_info):
        return http_reply.headers_for_cache(
            flask.make_response(
                _google_tag_manager_re.sub(
                    _google_tag_manager,
                    pkio.read_text(p),
                ), ),
            path=p,
        )
    if re.match(r'^html/[^/]+html$', path_info):
        return http_reply.render_html(p)
    return flask.send_file(p, conditional=True)
Beispiel #6
0
def auth_login(req):
    from sirepo import server

    if cfg.auth_secret:
        auth_hash(req, verify=True)
    # DEPRECATED
    elif not server.cfg.enable_bluesky:
        util.raise_not_found('bluesky is not enabled')
    sid = req.simulationId
    sim_type = req.simulationType
    path = simulation_db.find_global_simulation(
        sim_type,
        sid,
        checked=True,
    )
    server.session_user(simulation_db.uid_from_dir_name(path))
Beispiel #7
0
def find_global_simulation(sim_type, sid, checked=False):
    paths = pkio.sorted_glob(user_dir_name().join('*', sim_type, sid))
    if len(paths) == 1:
        return str(paths[0])
    if len(paths) == 0:
        if checked:
            util.raise_not_found(
                '{}/{}: global simulation not found',
                sim_type,
                sid,
            )
        return None
    util.raise_not_found(
        '{}: more than one path found for simulation={}/{}',
        paths,
        sim_type,
        sid,
    )
Beispiel #8
0
def find_global_simulation(sim_type, sid, checked=False):
    paths = pkio.sorted_glob(user_dir_name().join('*', sim_type, sid))
    if len(paths) == 1:
        return str(paths[0])
    if len(paths) == 0:
        if checked:
            util.raise_not_found(
                '{}/{}: global simulation not found',
                sim_type,
                sid,
            )
        return None
    util.raise_not_found(
        '{}: more than one path found for simulation={}/{}',
        paths,
        sim_type,
        sid,
    )
Beispiel #9
0
def _dispatch(path):
    """Called by Flask and routes the base_uri with parameters

    Args:
        path (str): what to route

    Returns:
        Flask.response
    """
    cookie.init()
    try:
        if path is None:
            return _dispatch_call(_empty_route.func, {})
        # werkzeug doesn't convert '+' to ' '
        parts = re.sub(r'\+', ' ', path).split('/')
        try:
            route = _uri_to_route[parts[0]]
            parts.pop(0)
        except KeyError:
            route = _default_route
        kwargs = pkcollections.Dict()
        for p in route.params:
            if not parts:
                if not p.is_optional:
                    raise NotFound('{}: uri missing parameter ({})', path,
                                   p.name)
                break
            if p.is_path_info:
                kwargs[p.name] = '/'.join(parts)
                parts = None
                break
            kwargs[p.name] = parts.pop(0)
        if parts:
            raise NotFound('{}: unknown parameters in uri ({})', parts, path)
        return _dispatch_call(route.func, kwargs)
    except NotFound as e:
        util.raise_not_found(e.log_fmt, *e.args, **e.kwargs)
    except Exception as e:
        pkdlog('{}: error: {}', path, pkdexc())
        raise
Beispiel #10
0
def api_findByName(simulation_type, application_mode, simulation_name):
    sim_type = sirepo.template.assert_sim_type(simulation_type)
    # use the existing named simulation, or copy it from the examples
    rows = simulation_db.iterate_simulation_datafiles(
        sim_type,
        simulation_db.process_simulation_list,
        {
            'simulation.name': simulation_name,
            'simulation.isExample': True,
        },
    )
    if len(rows) == 0:
        for s in simulation_db.examples(sim_type):
            if s['models']['simulation']['name'] != simulation_name:
                continue
            simulation_db.save_new_example(s)
            rows = simulation_db.iterate_simulation_datafiles(
                sim_type,
                simulation_db.process_simulation_list,
                {
                    'simulation.name': simulation_name,
                },
            )
            break
        else:
            util.raise_not_found(
                'simulation not found by name={} type={}',
                simulation_name,
                sim_type,
            )
    # format the uri for the local route to this simulation for application_mode
    s = simulation_db.get_schema(sim_type)
    m = s.appModes[application_mode]
    r = m.localRoute
    assert r in s.localRoutes
    u = '/{}#/{}/{}'.format(sim_type, r, rows[0].simulationId)
    if m.includeMode:
        u += '?application_mode={}'.format(application_mode)
    return http_reply.gen_redirect_for_anchor(u)
Beispiel #11
0
def _dispatch(path):
    """Called by Flask and routes the base_uri with parameters

    Args:
        path (str): what to route

    Returns:
        Flask.response
    """
    cookie.init()
    try:
        if path is None:
            return _dispatch_call(_empty_route.func, {})
        # werkzeug doesn't convert '+' to ' '
        parts = re.sub(r'\+', ' ', path).split('/')
        try:
            route = _uri_to_route[parts[0]]
            parts.pop(0)
        except KeyError:
            route = _default_route
        kwargs = pkcollections.Dict()
        for p in route.params:
            if not parts:
                if not p.is_optional:
                    raise NotFound('{}: uri missing parameter ({})', path, p.name)
                break
            if p.is_path_info:
                kwargs[p.name] = '/'.join(parts)
                parts = None
                break
            kwargs[p.name] = parts.pop(0)
        if parts:
            raise NotFound('{}: unknown parameters in uri ({})', parts, path)
        return _dispatch_call(route.func, kwargs)
    except NotFound as e:
        util.raise_not_found(e.log_fmt, *e.args, **e.kwargs)
    except Exception as e:
        pkdlog('{}: error: {}', path, pkdexc())
        raise
Beispiel #12
0
def api_findByName(simulation_type, application_mode, simulation_name):
    # use the existing named simulation, or copy it from the examples
    rows = simulation_db.iterate_simulation_datafiles(simulation_type, simulation_db.process_simulation_list, {
        'simulation.name': simulation_name,
        'simulation.isExample': True,
    })
    if len(rows) == 0:
        for s in simulation_db.examples(simulation_type):
            if s['models']['simulation']['name'] == simulation_name:
                simulation_db.save_new_example(s)
                rows = simulation_db.iterate_simulation_datafiles(simulation_type, simulation_db.process_simulation_list, {
                    'simulation.name': simulation_name,
                })
                break
        else:
            util.raise_not_found('{}: simulation not found by name: {}', simulation_type, simulation_name)
    return javascript_redirect(
        uri_router.format_uri(
            simulation_type,
            application_mode,
            rows[0]['simulationId'],
            simulation_db.get_schema(simulation_type)
        )
    )
Beispiel #13
0
def auth_hash(req, verify=False):
    now = int(time.time())
    if not 'authNonce' in req:
        if verify:
            util.raise_not_found('authNonce: missing field in request')
        r = random.SystemRandom()
        req.authNonce = str(now) + _AUTH_NONCE_SEPARATOR + ''.join(
            r.choice(_AUTH_NONCE_CHARS) for x in range(_AUTH_NONCE_UNIQUE_LEN))
    h = hashlib.sha256()
    h.update(
        _AUTH_HASH_SEPARATOR.join([
            req.authNonce,
            req.simulationType,
            req.simulationId,
            cfg.auth_secret,
        ]), )
    res = 'v1:' + base64.urlsafe_b64encode(h.digest())
    if not verify:
        req.authHash = res
        return
    if res != req.authHash:
        util.raise_not_found(
            '{}: hash mismatch expected={} nonce={}',
            req.authHash,
            res,
            req.authNonce,
        )
    t = req.authNonce.split(_AUTH_NONCE_SEPARATOR)[0]
    try:
        t = int(t)
    except ValueError as e:
        util.raise_not_found(
            '{}: auth_nonce prefix not an int: nonce={}',
            t,
            req.authNonce,
        )
    delta = now - t
    if abs(delta) > _AUTH_NONCE_REPLAY_SECS:
        util.raise_not_found(
            '{}: auth_nonce time outside replay window={} now={} nonce={}',
            t,
            _AUTH_NONCE_REPLAY_SECS,
            now,
            req.authNonce,
        )
Beispiel #14
0
def auth_hash(req, verify=False):
    now = int(time.time())
    if not 'authNonce' in req:
        if verify:
           util.raise_not_found('authNonce: missing field in request')
        req.authNonce = str(now) + _AUTH_NONCE_SEPARATOR + util.random_base62()
    h = hashlib.sha256()
    h.update(
        _AUTH_HASH_SEPARATOR.join([
            req.authNonce,
            req.simulationType,
            req.simulationId,
            cfg.auth_secret,
        ]),
    )
    res = 'v1:' + base64.urlsafe_b64encode(h.digest())
    if not verify:
        req.authHash = res
        return
    if res != req.authHash:
        util.raise_not_found(
            '{}: hash mismatch expected={} nonce={}',
            req.authHash,
            res,
            req.authNonce,
        )
    t = req.authNonce.split(_AUTH_NONCE_SEPARATOR)[0]
    try:
        t = int(t)
    except ValueError as e:
        util.raise_not_found(
            '{}: auth_nonce prefix not an int: nonce={}',
            t,
            req.authNonce,
        )
    delta = now - t
    if abs(delta) > _AUTH_NONCE_REPLAY_SECS:
        util.raise_not_found(
            '{}: auth_nonce time outside replay window={} now={} nonce={}',
            t,
            _AUTH_NONCE_REPLAY_SECS,
            now,
            req.authNonce,
        )