Exemplo n.º 1
0
class Service(object, metaclass=Singleton):
    def __init__(self):
        self.repository = Repository()

    @log
    def save(self, body):
        entity = json.loads(body, cls=EntityDecoder)
        return json.dumps(self.repository.save(entity=entity),
                          cls=EntityEncoder)

    @log
    def update(self, body):
        entity = json.loads(body, cls=EntityDecoder)
        return json.dumps(self.repository.update(entity=entity),
                          cls=EntityEncoder)

    @log
    def remove(self, body):
        entity = json.loads(body, cls=EntityDecoder)
        return json.dumps(self.repository.remove(entity=entity))

    @log
    def remove_by_id(self, body):
        return json.dumps(
            self.repository.remove_by_id(entity_id=json.loads(body)['id']))

    @log
    def get(self, entity_id):
        return json.dumps(self.repository.get(entity_id=entity_id),
                          cls=EntityEncoder)
Exemplo n.º 2
0
class Serice(object, metaclass=Singleton):
    def __init__(self):
        self.repository = Repository()

    @log
    def get_all(self):
        entities = [Entity(int(x[0]), x[1]) for x in self.repository.get_all()]
        return json.dumps(entities, cls=EntityJsonEncoder)

    @log
    def get_by_id(self, id):
        r = self.repository.get_by_id(id)
        entity = r and Entity(int(r[0]), r[1]) or Entity()
        return json.dumps(entity, cls=EntityJsonEncoder)

    @log
    def save(self, entity):
        return json.dumps(self.repository.save(
            json.loads(entity, cls=EntityJsonDecoder)),
                          cls=EntityJsonEncoder)

    @log
    def delete_by_id(self, id):
        return json.dumps(self.repository.delete_by_id(id))

    @log
    def update(self, entity):
        return json.dumps(self.repository.update(
            json.loads(entity, cls=EntityJsonDecoder)),
                          cls=EntityJsonEncoder)
Exemplo n.º 3
0
    def test_receive_obs_error(self):
        """Test error handling in the receive routine."""

        repository = Repository()
        station_id = 1

        # Check what happens if the path is misconfigured (or the server is not able to write file)
        self.app.root = app.config["storage"][
            'image_root'] = '/nonexistent/path'
        secret = repository.read_station_secret(station_id)

        data = {
            'aos': datetime.datetime(2020, 3, 28, 12, 00),
            'tca': datetime.datetime(2020, 3, 28, 12, 15),
            'los': datetime.datetime(2020, 3, 28, 12, 30),
            'sat': 'NOAA 15',
            # 'notes': optional,
            "file0": open("tests/x.png", 'rb'),
            "file1": open("tests/x.png", 'rb')
        }

        header_value = get_authorization_header_value(str(station_id), secret,
                                                      data)
        headers = {'Authorization': header_value}
        response = self.app.post('/receive', data=data, headers=headers)

        self.assertEqual(response.status_code, 503)

        # Check if there's appropriate entry in the log file.
        self.check_log([
            "Failed to write /nonexistent/path/",
            "tests_x.png (image_root=/nonexistent/path)"
        ])
Exemplo n.º 4
0
def _get_secret(station_id) -> bytes:
    '''
    Fetch station secret from database

    ToDo: Returned value should be cached to avoid DDoS and
          DB call before authorization
    '''
    repository = Repository()
    return repository.read_station_secret(station_id)
Exemplo n.º 5
0
    def test_read_observation(self, repository: Repository):
        obs = repository.read_observation(ObservationId(750))
        self.assertIsNotNone(obs)

        # Now check if the response is as expected.
        self.check_obs750(obs)  # type: ignore

        # Now test negative case. There's nos uch observation
        obs = repository.read_observation(ObservationId(12345))
        assert obs == None
Exemplo n.º 6
0
def login():

    repository = Repository()

    if current_user.is_authenticated:
        stations = repository.owned_stations(current_user.get_id())

        # list of stations
        l = " ".join(f"{s['name']}({s['station_id']})" for s in stations)
        app.logger.info("Authenticated user %s, owner of %s" %
                        (current_user.username, l))

        return render_template("login.html",
                               user=current_user,
                               stations=stations)

    form = LoginForm()

    if form.validate_on_submit():
        app.logger.info(
            "Login requested for user %s, pass=%s, remember_me=%s" %
            (form.username.data, form.password.data, form.remember.data))

        user = repository.read_user(user=form.username.data)

        if user is None:
            app.logger.info("Login failed: invalid username: %s" %
                            form.username.data)
            flash("Invalid username.")
            return redirect(url_for("login"))

        u = ApplicationUser(user)
        if not u.check_password(form.password.data):
            app.logger.info("Login failed: invalid password %s for user %s" %
                            (form.password.data, form.username.data))
            flash("Invalid password.")
            return redirect(url_for("login"))

        if u.role == UserRole.BANNED:
            app.logger.info(
                "Login failed: attempt to login into disabled account %s" %
                form.username.data)
            flash("Account disabled.")
            return redirect(url_for("login"))

        app.logger.info("Login successful for user %s" % form.username.data)
        login_user(u, remember=form.remember.data)

        next_page = request.args.get("next")
        if not next_page or url_parse(next_page).netloc != "":
            next_page = url_for("index")
        return redirect(next_page)

    return render_template("login.html", form=form)
Exemplo n.º 7
0
    def test_db_version(self, mock_connect):
        repostory = Repository({})
        mock_cursor = mock_connect.return_value.cursor.return_value
        mock_cursor.fetchone.side_effect = [{
            "count": 1
        }, (3, ), {
            "version": 15
        }]

        version = repostory.get_database_version()
        self.assertEqual(version, 15)
Exemplo n.º 8
0
    def test_user_role(self, repository: Repository):
        """Tests conversion of string to user roles."""
        self.assertEqual(repository.user_role_to_enum('REGULAR'),
                         UserRole.REGULAR)
        self.assertEqual(repository.user_role_to_enum('OWNER'), UserRole.OWNER)
        self.assertEqual(repository.user_role_to_enum('ADMIN'), UserRole.ADMIN)
        self.assertEqual(repository.user_role_to_enum('BANNED'),
                         UserRole.BANNED)

        self.assertRaises(LookupError, repository.user_role_to_enum,
                          'moderator')  # no such role
Exemplo n.º 9
0
    def test_station(self, repository: Repository):
        """Check that a single station data is returned properly."""
        station = repository.read_station(1)
        statistics = repository.read_station_statistics(1)
        self.assertIsNotNone(station)
        self.assertIsNotNone(statistics)
        self.check_station1(station, statistics)

        # Now check invalid case. There's no such station
        station = repository.read_station(123)
        statistics = repository.read_station_statistics(123)
        self.assertIsNone(station)
        self.assertIsNone(statistics)
Exemplo n.º 10
0
    def test_receive_obs(self):
        repository = Repository()
        station_id = 1
        secret = repository.read_station_secret(station_id)

        data = {
            'aos':
            datetime.datetime(2020, 3, 28, 12, 00),
            'tca':
            datetime.datetime(2020, 3, 28, 12, 15),
            'los':
            datetime.datetime(2020, 3, 28, 12, 30),
            'sat':
            'NOAA 15',
            'config':
            '{"text":"note text"}',
            "file0":
            open("tests/x.png", 'rb'),
            "file1":
            open("tests/x.png", 'rb'),
            "tle": [
                # Include trailling character
                "1 25544U 98067A   08264.51782528 -.00002182  00000-0 -11606-4 0  2927 ",
                "2 25544  51.6416 247.4627 0006703 130.5360 325.0288 15.72125391563537"
            ],
            "rating":
            0.75
        }

        header_value = get_authorization_header_value(str(station_id), secret,
                                                      data)
        headers = {'Authorization': header_value}
        response = self.app.post('/receive', data=data, headers=headers)
        self.assertEqual(response.status_code, 204)
        file_count = lambda dir_: len([
            f for f in os.listdir(dir_)
            if os.path.isfile(os.path.join(dir_, f))
        ])
        self.assertEqual(file_count(IMAGE_ROOT), 2)
        self.assertEqual(file_count(os.path.join(IMAGE_ROOT, "thumbs")), 1)
        chart_dir = os.path.join(IMAGE_ROOT, "charts")
        self.assertEqual(file_count(chart_dir), 2)
        chart_files = sorted(os.listdir(chart_dir))
        self.assertEqual(chart_files, ["by_time-1.png", "polar-1.png"])
        # Todo: Need to check if the DB entries have been added.

        # Check if there are appropriate entries in the log file.
        self.check_log([
            "0-tests_x.png written to tests/images",
            "1-tests_x.png written to tests/images"
        ])
Exemplo n.º 11
0
    def test_satellites(self, repository: Repository):
        """Test that a list of satellites is returned properly."""
        satellites = repository.read_satellites()
        self.assertEqual(len(satellites), 3)
        self.assertEqual(satellites[-1]['sat_id'], 33591)
        self.assertEqual(satellites[-2]['sat_id'], 28654)
        self.assertEqual(satellites[-3]['sat_id'], 25338)

        satellites = repository.read_satellites(limit=2)
        self.assertEqual(len(satellites), 2)
        self.assertEqual(satellites[-1]['sat_id'], 28654)
        self.assertEqual(satellites[-2]['sat_id'], 25338)

        satellites = repository.read_satellites(offset=2)
        self.assertEqual(len(satellites), 1)
        self.assertEqual(satellites[-1]['sat_id'], 33591)
Exemplo n.º 12
0
def create_repo():
    request_data = request.get_json()
    new_repo = None
    repo_id = None
    repo_url = None
    expires = None
    try:
        new_repo = Repository.from_request(request_data)
    except AttributeError as e:
        abort(400, 'Bad request. %s' % e.__cause__)

    try:
        if new_repo is not None:
            (repo_id, repo_url) = new_repo.init()
            builder = BuildPipeline(new_repo)
            builder.execute()
            expires = RepoUtils.get_expiration_date(repo_id)
    except RepositoryError as e:
        current_app.logger.error(e.__str__())
        deploy_error_page(new_repo.deploy_path)
    except OSError as e:
        current_app.logger.error(e.__str__())
        deploy_error_page(new_repo.deploy_path)
    finally:
        if repo_url is not None and repo_id is not None and expires is not None:
            return jsonify({
                Constants.RESPONSE_PARAMS['PREVIEW_URL']: repo_url,
                Constants.RESPONSE_PARAMS['PREVIEW_EXPIRATION']: expires,
                Constants.RESPONSE_PARAMS['PREVIEW_ID']: repo_id
            })
        else:
            abort(502)
Exemplo n.º 13
0
 def test_owned_stations(self, repository: Repository):
     """Tests that it's possible to get a list of stations a given user is allowed to manage."""
     stations = repository.owned_stations(
         5)  # get the list of stations that user with user_id=5 owns.
     self.assertEqual(len(stations), 1)
     self.assertEqual(stations[0]['name'], 'TKiS-1')
     self.assertEqual(stations[0]['station_id'], 1)
Exemplo n.º 14
0
    def test_satellite(self, repository: Repository):
        """Checks that a single satellite data is returned properly."""
        sat = repository.read_satellite(25338)
        self.assertIsNotNone(sat)

        self.assertEqual(sat['sat_id'], 25338)
        self.assertEqual(sat['sat_name'], 'NOAA 15')

        sat = repository.read_satellite('NOAA 19')
        self.assertEqual(sat['sat_id'], 33591)
        self.assertEqual(sat['sat_name'], 'NOAA 19')

        sat = repository.read_satellite(12345)
        self.assertIsNone(sat)  # :( No such thing yet.

        sat = repository.read_satellite('GDANSKSAT-1')
        self.assertIsNone(sat)  # :( No such thing yet.
Exemplo n.º 15
0
    def test_is_station_owner(self, repository: Repository):
        """Tests if the ownership relation can be checked properly. The input data is defined in the db-data.psql file.
           Here it's copied for convenience: (1,1), (2,1), (3,1), (5,1), (4,2)"""
        cases = [[1, 1, True], [2, 2, False], [2, 1, True], [3, 1, True],
                 [4, 1, False], [5, 1, True], [4, 2, True]]

        for c in cases:
            # Checking if user {c[0]} owns the station {c[1]}, expected result {c[2]}
            self.assertEqual(repository.is_station_owner(c[0], c[1]), c[2])
Exemplo n.º 16
0
def obs(obs_id: ObservationId = None, limit_and_offset=None):
    if obs_id is None:
        abort(300, description="ID is required")
        return

    repository = Repository()
    with repository.transaction():
        observation = repository.read_observation(obs_id)

        orbit = None

        if observation is None:
            abort(404, "Observation not found")

        files = repository.read_observation_files(observation["obs_id"],
                                                  **limit_and_offset)
        files_count = repository.count_observation_files(obs_id)
        satellite = repository.read_satellite(observation["sat_id"])

        orbit = observation
        if observation['tle'] is not None:
            # observation['tle'] is always an array of exactly 2 strings.
            orbit = parse_tle(*observation['tle'], satellite["sat_name"])

        station = repository.read_station(observation["station_id"])

    # Now tweak some observation parameters to make them more human readable
    observation = human_readable_obs(observation)

    # Now determine if there is a logged user and if there is, if this user is the owner of this
    # station. If he is, we should show the admin panel.
    user_id = 0
    owner = False
    if current_user.is_authenticated:
        user_id = current_user.get_id()

        # Check if the current user is the owner of the station.
        station_id = station['station_id']

        owner = repository.is_station_owner(user_id, station_id)

    return 'obs.html', dict(obs=observation,
                            files=files,
                            sat_name=satellite["sat_name"],
                            item_count=files_count,
                            orbit=orbit,
                            station=station,
                            is_owner=owner)
Exemplo n.º 17
0
def station(station_id=None):

    repository = Repository()
    station = repository.read_station(station_id)
    if station is None:
        abort(404, "Station not found")
    statistics = repository.read_station_statistics(station["station_id"])

    photos = repository.read_station_photos(station_id)

    owners = repository.station_owners(station_id)

    # Now get 3 latest observations from this station
    filters = {"station_id": station['station_id']}
    latest_obs = repository.read_observations(filters=filters,
                                              limit=3,
                                              offset=0)

    # Get the 3 observations with the best rating
    best_obs = repository.read_observations(filters=filters,
                                            limit=3,
                                            offset=0,
                                            order="r.rating DESC",
                                            expr="r.rating is not NULL")

    x = {}
    x['station_id'] = station['station_id']
    x['name'] = station['name']
    x['coords'] = utils.coords(station['lon'], station['lat'])
    x['descr'] = station['descr']

    x['config'] = station['config']
    x['registered'] = station['registered']
    x['lastobs'] = statistics["last_los"]
    x['firstobs'] = statistics["first_aos"]
    x['cnt'] = statistics["observation_count"]

    files = []
    for photo in photos:
        y = {}
        y['filename'] = photo['filename']
        y['descr'] = photo['descr']
        y['sort'] = photo['sort']
        files.append(y)

    return render_template('station.html',
                           station=x,
                           files=files,
                           owners=owners,
                           latest_obs=latest_obs,
                           best_obs=best_obs)
Exemplo n.º 18
0
    def test_read_observations(self, repository: Repository):
        """Check if a list of observations is returned properly."""
        obslist = repository.read_observations()

        # Make sure there are at least 3 observations (more may be added in the future.
        # This test should be future-proof.)
        self.assertGreaterEqual(len(obslist), 3)

        # Check if the data returned matches values from tests/db-data.psql
        self.check_obs750(obslist[-1])
        self.check_obs751(obslist[-2])
        self.check_obs752(obslist[-3])
Exemplo n.º 19
0
    def test_station_owners(self, repository: Repository):
        """Tests that the owners of a station can be returned properly. This query is used on
           the station page to list its owners."""
        owners1 = repository.station_owners(1)  # List owners of station id 1
        owners5 = repository.station_owners(
            5
        )  # List owners of station id 5 (no such station, so should be empty list)

        # See tests/db-data.psql for details (station_owners table)
        self.assertEqual(len(owners1), 4)
        self.assertEqual(owners1[0]['username'], 'asimov')
        self.assertEqual(owners1[0]['id'], 1)
        self.assertEqual(owners1[1]['username'], 'baxter')
        self.assertEqual(owners1[1]['id'], 2)
        self.assertEqual(owners1[2]['username'], 'clarke')
        self.assertEqual(owners1[2]['id'], 3)
        self.assertEqual(owners1[3]['username'], 'admin')
        self.assertEqual(owners1[3]['id'], 5)

        # No such station, so no owners
        self.assertEqual(len(owners5), 0)
Exemplo n.º 20
0
    def test_stations(self, repository: Repository):
        """Checks that a list of stations is returned properly."""
        station_entries = repository.read_stations()
        station_statistics = repository.read_stations_statistics()
        self.assertEqual(len(station_entries), 2)
        self.assertEqual(len(station_statistics), 2)
        s1, s2 = zip(station_entries, station_statistics)

        self.check_station1(*s1)
        self.check_station2(*s2)

        # Now limit number of returned stations to just one. There should be only station-id 1.
        station_entries = repository.read_stations(limit=1)
        station_statistics = repository.read_stations_statistics(limit=1)
        self.assertEqual(len(station_entries), 1)
        self.assertEqual(len(station_statistics), 1)
        self.check_station1(station_entries[0], station_statistics[0]
                            )  # This should return values for station-id 1

        # Now skip the first station. Only station 2 should be returned.
        station_entries = repository.read_stations(offset=1)
        station_statistics = repository.read_stations_statistics(offset=1)
        self.assertEqual(len(station_entries), 1)
        self.assertEqual(len(station_statistics), 1)
        self.check_station2(station_entries[0], station_statistics[0]
                            )  # This should return values for station-id 2
Exemplo n.º 21
0
class Service(object, metaclass=Singleton):
    def __init__(self):
        self.repository = Repository()

    @log()
    @to_json(clazz=Entity)
    def save(self, body):
        return self.repository.save(body)

    @log()
    @to_json(clazz=Entity)
    def get(self, id):
        return self.repository.get(id)

    @log()
    def remove(self, id):
        return self.repository.remove(id)

    @log()
    @to_json(clazz=Entity)
    def update(self, body):
        return self.repository.update(body)
Exemplo n.º 22
0
def obs_delete(obs_id: ObservationId = None):

    # First check if such an observation even exists.
    repository = Repository()
    observation = repository.read_observation(obs_id)
    if observation is None:
        return render_template('obs_delete.html',
                               status=["There is no observation %s" % obs_id],
                               obs_id=obs_id)

    # Second, check if the guy is logged in.
    if not current_user.is_authenticated:
        return render_template(
            'obs_delete.html',
            status=["You are not logged in, you can't delete anything."],
            obs_id=obs_id)

    # Ok, at least this guy is logged in. Let's check who he is.
    user_id = current_user.get_id()

    # Check if the current user is the owner of the station.
    station = repository.read_station(observation["station_id"])
    station_id = station['station_id']

    owner = repository.is_station_owner(user_id, station_id)

    if not owner:
        return render_template(
            'obs_delete.html',
            status=[
                "You are not the owner of station %s, you can't delete observation %s."
                % (station.name, obs_id)
            ],
            obs_id=obs_id)

    # If you got that far, this means the guy is logged in, he's the owner and is deleting his own observation.

    status = obs_delete_db_and_disk(repository, obs_id)
    return render_template('obs_delete.html', status=status, obs_id=obs_id)
Exemplo n.º 23
0
def obs_delete_db_and_disk(repository: Repository, obs_id: ObservationId):

    app.logger.info("About to delete observation %s and all its files" %
                    obs_id)

    # Step 1: Create a list of files to be deleted. There may be several products.
    products = repository.read_observation_files(obs_id)
    obs = repository.read_observation(obs_id)
    files = [[f['filename'], "product"] for f in products]

    # Step 2: thumbnail is stored with the observation. There's at most one thumbnail.
    files.append([os.path.join("thumbs", obs['thumbnail']), "thumbnail"])

    # Step 3: And there are two charts: alt-az pass chart and polar pass chart.
    files.append(
        [os.path.join("charts", "by_time-%s.png" % obs_id), "pass chart"])
    files.append(
        [os.path.join("charts", "polar-%s.png" % obs_id), "polar pass chart"])

    # All those files are stored in this dir
    root = app.config["storage"]['image_root']

    status = []
    for f in files:
        path = os.path.join(root, f[0])
        app.logger.info("Trying to delete [%s]" % path)
        try:
            os.remove(path)
            status.append("Deleted %s file %s." % (f[1], f[0]))
        except Exception as ex:
            status.append("Failed to delete %s file: %s, reason: %s" %
                          (f[1], path, repr(ex)))

    # Step 4: delete entries in the db
    repository.delete_observation(obs_id)
    status.append("DB removal complete.")

    return status
Exemplo n.º 24
0
class Service(metaclass=Singleton):
    def __init__(self):
        self.repository = Repository()

    @log
    def save(self, body):
        entity = json.loads(body, cls=EntityDecoder)

        return json.dumps(self.repository.create(entity), cls=EntityEncoder)

    @log
    def remove(self, id):
        return json.dumps(self.repository.remove(id), cls=EntityEncoder)

    @log
    def get(self, id):
        return json.dumps(self.repository.get(id), cls=EntityEncoder)

    @log
    def update(self, body):
        entity = json.loads(body, cls=EntityDecoder)

        return json.dumps(self.repository.update(entity), cls=EntityEncoder)
Exemplo n.º 25
0
class AppHandler(tornado.web.RequestHandler):
    def initialize(self):
        self.repository = Repository()

    def get(self):
        self.write(
            json.dumps(self.repository.get(self.get_argument('id')),
                       cls=EntityEncoder))

    def post(self):
        self.write(
            json.dumps(self.repository.update(
                json.loads(self.request.body, cls=EntityDecoder)),
                       cls=EntityEncoder))

    def put(self):
        self.write(
            json.dumps(self.repository.create(
                json.loads(self.request.body, cls=EntityDecoder)),
                       cls=EntityEncoder))

    def delete(self):
        self.write(json.dumps(self.repository.remove(self.get_argument('id'))))
Exemplo n.º 26
0
def stations(limit_and_offset):
    '''This function retrieves list of all registered ground stations.'''
    repository = Repository()
    stations = repository.read_stations(**limit_and_offset)
    statistics = repository.read_stations_statistics(**limit_and_offset)
    station_count = repository.count_stations()
    # Now convert the data to a list of objects that we can pass to the template.
    stationlist = []

    for station, stat in zip(stations, statistics):
        x = {}
        x['station_id'] = station['station_id']
        x['name'] = station['name']
        x['coords'] = utils.coords(station['lon'], station['lat'])
        x['descr'] = station['descr']
        x['config'] = station['config']
        x['registered'] = station['registered']
        x['lastobs'] = stat["last_los"]
        x['cnt'] = stat["observation_count"]

        stationlist.append(x)

    return 'stations.html', dict(stations=stationlist,
                                 item_count=station_count)
Exemplo n.º 27
0
    def test_observations_filters(self, repository: Repository):
        filters: ObservationFilter = {"obs_id": ObservationId(751)}
        observations = repository.read_observations(filters=filters)
        self.assertEqual(len(observations), 1)
        self.assertEqual(observations[0]["obs_id"], 751)

        # Include observations partially (of fully) in date range
        #   AOS before > LOS after
        filters = {
            "aos_before": datetime.datetime(2020, 3, 8, 15, 45, 0, 0),
            "los_after": datetime.datetime(2020, 3, 8, 15, 30, 0)
        }
        observations = repository.read_observations(filters=filters)
        self.assertEqual(len(observations), 1)
        self.assertEqual(observations[0]["obs_id"], 750)

        filters = {"sat_id": SatelliteId(28654)}
        observations = repository.read_observations(filters=filters)
        self.assertEqual(len(observations), 2)
        self.assertEqual(observations[0]["obs_id"], 1276)
        self.assertEqual(observations[1]["obs_id"], 752)

        filters = {"station_id": StationId(1)}
        observations = repository.read_observations(filters=filters)
        self.assertEqual(len(observations), 4)

        filters = {"notes": "ote"}
        observations = repository.read_observations(filters=filters)
        self.assertEqual(len(observations), 1)
        self.assertEqual(observations[0]["notes"], "Note")

        filters = {"has_tle": True}
        observations = repository.read_observations(filters=filters)
        self.assertEqual(len(observations), 2)  # obs 751 and 1276
        self.assertIsNotNone(observations[0]["tle"])
        self.assertIsNotNone(observations[1]["tle"])

        filters = {
            "sat_id": SatelliteId(25338),
            "station_id": StationId(1),
            "has_tle": True,
            "los_after": datetime.datetime(2020, 3, 8, 15, 30, 0)
        }
        observations = repository.read_observations(filters=filters)
        self.assertEqual(len(observations), 1)
        self.assertEqual(observations[0]["obs_id"], 751)
Exemplo n.º 28
0
def migrate(config=None, migration_directory="db"):
    '''
    Perform migrations.

    Parameters
    ==========
    config
        Dictionary with psycopg2 "connect" method arguments.
        If None then read INI file
    migration_directory: str
        Directory with .psql files. Files must to keep naming convention:
            svarog-XX.psql
        where XX is number of database revision.

    Returns
    =======
    Function print migration status on console. Changes are save in database.

    Notes
    =====
    If any migration fail then all changes are revert.
    '''
    repository = Repository(config)

    db_version = repository.get_database_version()

    migrations = list_migrations(migration_directory)

    with repository.transaction() as transaction:
        for migration_version, migration_path in migrations:
            if migration_version <= db_version:
                print("Skip migration to %d version" % (migration_version, ))
                continue

            print("Process migration to %d version..." % (migration_version, ),
                  end="")
            with open(migration_path) as migration_file:
                content = migration_file.read()

            repository.execute_raw_query(content)
            print("OK")

        transaction.commit()

    new_db_version = repository.get_database_version()
    print("Migration complete from %d to %d!" % (db_version, new_db_version))
Exemplo n.º 29
0
    def test_user(self, repository: Repository):
        """Test if user data can be retrieved automatically."""

        nonexistent = repository.read_user(user="******")
        self.assertIsNone(nonexistent)

        nonexistent = repository.read_user(user=6)
        self.assertIsNone(nonexistent)

        user1 = repository.read_user(user="******")
        self.assertEqual(user1['username'], 'clarke')
        self.assertEqual(
            user1['digest'],
            'pbkdf2:sha256:150000$Ij6XJyek$d6a0cd085e6955843a9c3224ccf24088852207d55bb056aa0b544168f94860b8'
        )  # sha256('password')
        self.assertEqual(user1['email'], '*****@*****.**')
        self.assertEqual(user1['role'], UserRole.ADMIN)

        user2 = repository.read_user(user=3)
        self.assertEqual(user2['username'], 'clarke')
        self.assertEqual(
            user2['digest'],
            'pbkdf2:sha256:150000$Ij6XJyek$d6a0cd085e6955843a9c3224ccf24088852207d55bb056aa0b544168f94860b8'
        )  # sha256('password')
        self.assertEqual(user2['email'], '*****@*****.**')
        self.assertEqual(user2['role'], UserRole.ADMIN)

        self.assertEqual(user1, user2)

        # UserRole field is enum, better be safe and check all possible combinations.
        user = repository.read_user(user='******')
        self.assertEqual(user['role'], UserRole.REGULAR)

        user = repository.read_user(user='******')
        self.assertEqual(user['role'], UserRole.OWNER)

        user = repository.read_user(user='******')
        self.assertEqual(user['role'], UserRole.BANNED)
Exemplo n.º 30
0
def obslist(limit_and_offset, **filters):
    '''This function retrieves observations list from a local database and
        displays it.'''
    aos_before_org = filters.get("aos_before")
    if aos_before_org is not None:
        # Repository uses datetime.datetime structure to bound dates and it is
        # exact date.
        # User provides datetime.date (which not include hour) and it means that
        # list should contain observations from @los_after day 00:00:00 hour to
        # @aos_before day 23:59:59.999 hour. For handle it we add 1 day to
        # @aos_before day before send to repository.
        filters["aos_before"] = aos_before_org + timedelta(days=1)

    repository = Repository()
    obslist = repository.read_observations(filters, **limit_and_offset)
    satellites_list = repository.read_satellites()
    observation_count = repository.count_observations(filters)
    stations_list = repository.read_stations()

    satellites_dict = {
        sat["sat_id"]: sat["sat_name"]
        for sat in satellites_list
    }
    stations_dict = {s["station_id"]: s["name"] for s in stations_list}
    for obs in obslist:
        obs["sat_name"] = satellites_dict[obs["sat_id"]]
        obs["station_name"] = stations_dict[obs["station_id"]]

    if aos_before_org is not None:
        # We send back to user the same date as user provide.
        filters["aos_before"] = aos_before_org

    # When database will contain many satellites and stations then we need
    # refactor this code to lazy, async read satellites and stations.
    return 'obslist.html', dict(obslist=obslist,
                                item_count=observation_count,
                                satellites=satellites_list,
                                stations=stations_list,
                                filters=filters)