Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance/user-others #6

Open
wants to merge 18 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ assignees: ''

---

**Is your feature request related to a problem? Please describe.**
**Is your feature request related to a problem? Please describe?**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
Expand Down
12 changes: 6 additions & 6 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,29 @@
- [ ] πŸ€– Build or CI
- [ ] ❓ Other (please specify)

## Related Issue :
## Related Issue:

- Resolve #123example

## What does this PR do ?
## What does this PR do?

A brief description of how this solves the issue.

## Consideration :
## Consideration:

Are there any alternatives considered / tried out during development for solution ? Any specific decision made ? if Yes , explain

## How to test ?
## How to test?

Notes for the reviewer. How to test this change?

## Screenshots :
## Screenshots:

Please provide screenshots of the change.

## Checklists:

Checklist before requesting review :
Checklist before requesting review:

- πŸ“– Read the HOT Code of Conduct: <https://docs.hotosm.org/code-of-conduct>
- πŸ‘·β€β™€οΈ Create small PRs. In most cases, this will be possible.
Expand Down
45 changes: 44 additions & 1 deletion API/api_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@


def create_readme_content(default_readme, polygon_stats):
"""
Create content for the README file.

Args:
default_readme (str): The content of the default README file.
polygon_stats (dict): Statistics about polygons.

Returns:
str: The content for the README file.
"""
utc_now = dt.now(timezone.utc)
utc_offset = utc_now.strftime("%z")
readme_content = f"Exported Timestamp (UTC{utc_offset}): {dt.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S')}\n"
Expand All @@ -76,6 +86,19 @@ def create_readme_content(default_readme, polygon_stats):
def zip_binding(
working_dir, exportname_parts, geom_dump, polygon_stats, default_readme
):
"""
Create a ZIP archive with specified files and content

Args:
working_dir (str): The working directory where the archive will be created
exportname_parts (list): Parts of the export name
geom_dump (str): The path to the GeoJSON file containing geometry information
polygon_stats (dict): Statistics about polygons
default_readme (str): The content of the default README file

Returns:
dict: A dictionary containing additional files for the ZIP archive
"""
logging.debug("Zip Binding Started!")
upload_file_path = os.path.join(
working_dir, os.pardir, f"{exportname_parts[-1]}.zip"
Expand Down Expand Up @@ -143,6 +166,16 @@ def zip_binding(
soft_time_limit=DEFAULT_SOFT_TASK_LIMIT,
)
def process_raw_data(self, params, user=None):
"""
Process raw data based on provided parameters

Args:
params (dict): Parameters for processing raw data
user (str, optional): User information. Defaults to None

Raises:
ValueError: If retry limit is reached
"""
if self.request.retries > 0:
raise ValueError("Retry limit reached. Marking task as failed.")
params = RawDataCurrentParams(**params)
Expand Down Expand Up @@ -258,7 +291,7 @@ def process_raw_data(self, params, user=None):
f"Done Export : {exportname} of {round(inside_file_size/1000000)} MB / {geom_area} sqkm in {response_time_str}"
)
final_response = {
"download_url": download_url,
"downloadUrl": downloadUrl,
"file_name": params.file_name,
"process_time": response_time_str,
"query_area": f"{round(geom_area,2)} Sq Km",
Expand All @@ -280,6 +313,16 @@ def process_raw_data(self, params, user=None):
soft_time_limit=HDX_SOFT_TASK_LIMIT,
)
def process_custom_request(self, params, user=None):
"""
Process custom request based on provided parameters

Args:
params (dict): Parameters for processing the custom request
user (str, optional): User information. Defaults to None

Raises:
ValueError: If retry limit is reached
"""
if self.request.retries > 0:
raise ValueError("Retry limit reached. Marking task as failed.")
params = DynamicCategoriesModel(**params)
Expand Down
8 changes: 8 additions & 0 deletions API/auth/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@


class UserRole(Enum):
"""Assigning user role as integer"""
ADMIN = 1
STAFF = 2
GUEST = 3


class AuthUser(BaseModel):
"""Defining fields as attributes"""
id: int
username: str
img_url: Union[str, None]
Expand All @@ -26,12 +28,14 @@ class AuthUser(BaseModel):


def get_user_from_db(osm_id: int):
"""Get OSM ID from the user"""
auth = Users()
user = auth.read_user(osm_id)
return user


def get_osm_auth_user(access_token):
"""Get OSM access token from the user"""
try:
user = AuthUser(**osm_auth.deserialize_access_token(access_token))
except Exception as ex:
Expand All @@ -44,10 +48,12 @@ def get_osm_auth_user(access_token):


def login_required(access_token: str = Header(...)):
"""Get user's login details"""
return get_osm_auth_user(access_token)


def get_optional_user(access_token: str = Header(default=None)) -> AuthUser:
"""Get user's access token which is optional"""
if access_token:
return get_osm_auth_user(access_token)
else:
Expand All @@ -56,13 +62,15 @@ def get_optional_user(access_token: str = Header(default=None)) -> AuthUser:


def admin_required(user: AuthUser = Depends(login_required)):
"""Get admin login details"""
db_user = get_user_from_db(user.id)
if not db_user["role"] is UserRole.ADMIN.value:
raise HTTPException(status_code=403, detail="User is not an admin")
return user


def staff_required(user: AuthUser = Depends(login_required)):
"""Get staff login details"""
db_user = get_user_from_db(user.id)

# admin is staff too
Expand Down
2 changes: 1 addition & 1 deletion API/custom_exports.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
router = APIRouter(prefix="/custom", tags=["Custom Exports"])


@router.post("/snapshot/")
@router.post("/snapshot")
@limiter.limit(f"{RATE_LIMIT_PER_MIN}/minute")
@version(1)
async def process_custom_requests(
Expand Down
27 changes: 25 additions & 2 deletions API/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,19 @@
# Humanitarian OpenStreetmap Team
# 1100 13th Street NW Suite 800 Washington, D.C. 20005
# <info@hotosm.org>
import time


import time
import os
import psycopg2
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from fastapi_versioning import VersionedFastAPI
from slowapi import _rate_limit_exceeded_handler
from slowapi.errors import RateLimitExceeded
from pip._vendor import requests


from src.config import (
ENABLE_CUSTOM_EXPORTS,
Expand Down Expand Up @@ -75,7 +79,13 @@

os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"

app = FastAPI(title="Raw Data API ", swagger_ui_parameters={"syntaxHighlight": False})
app = FastAPI(
title="Raw Data API",
summary="Your one-stop API which is a set of high-performant APIs (Application Programming Interfaces) for transforming and exporting OpenStreetMap (OSM) data in different GIS file formats.",
swagger_ui_parameters={"syntaxHighlight": False},
)
# RAW Data API (Application Programming Interface) helps to transform and export OpenStreetMap (OSM) data in different GIS file formats.

app.include_router(auth_router)
app.include_router(raw_data_router)
app.include_router(tasks_router)
Expand Down Expand Up @@ -112,6 +122,19 @@
origins = ["*"]


class ConsoleColors:
BOLD = "\033[1m"
RESET = "\033[0m"
GREEN = "\033[92m"


welcome_msg = (
f"{COLOR_GREEN}Welcome to the HOTOSM raw data API!\n"
f"{COLOR_BOLD}Your one-stop API which is a set of high-performant APIs (Application Programming Interfaces) for transforming and exporting OpenStreetMap (OSM) data in different GIS file formats.{COLOR_RESET}"
)
print(welcome_msg)


@app.middleware("http")
async def add_process_time_header(request, call_next):
"""Times request and knows response time and pass it to header in every request
Expand Down
2 changes: 1 addition & 1 deletion API/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
router = APIRouter(prefix="/stats", tags=["Stats"])


@router.post("/polygon/")
@router.post("/polygon")
@limiter.limit(f"{POLYGON_STATISTICS_API_RATE_LIMIT}/minute")
@version(1)
async def get_polygon_stats(
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

**API Documentation** : https://api-prod.raw-data.hotosm.org/v1/redoc

`Raw Data API ` is a set of high-performant APIs for transforming and exporting OpenStreetMap (OSM) data in different GIS file formats.
`Raw Data API ` is a set of high-performant APIs(Application Programming Interface(s)) for transforming and exporting OpenStreetMap (OSM) data in different GIS file formats.

## Features

Expand Down
22 changes: 11 additions & 11 deletions backend/Manual.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Initialize Rawdata Loading

Prepare your osm.pbf for loading before start. You can download it from different sources such as Geofabrik , Planet.
Prepare your osm.pbf for loading before start. You can download it from different sources such as Geofabrik, Planet.

- Install [osm2pgsql v1.6.0](https://github.com/openstreetmap/osm2pgsql/releases/tag/1.6.0)
- Download and clone underpass
Expand All @@ -10,7 +10,7 @@ Prepare your osm.pbf for loading before start. You can download it from differen

> <font size="2">

You can Export following system variables in order to avoid passing db configuration time to time ( Optional )
You can xxport following system variables in order to avoid passing db configuration time to time ( Optional )

PGHOST behaves the same as the host connection parameter.
PGHOSTADDR behaves the same as the hostaddr connection parameter. This can be set instead of or in addition to PGHOST to avoid DNS lookup overhead.
Expand All @@ -33,7 +33,7 @@ export PGDATABASE=postgres

`osm2pgsql --create -H localhost -U admin -P 5432 -d postgres -W --extra-attributes --slim --output=flex --style ./raw.lua yourdownloaded.osm.pbf `

with exported DB Param :
with exported DB Param:

`osm2pgsql --create --extra-attributes --slim --output=flex --style ./raw.lua yourdownloaded.osm.pbf `

Expand Down Expand Up @@ -69,26 +69,26 @@ port=

```

- **Create Basic Indexes** :
- **Create Basic Indexes**:

```
psql -h localhost -U admin -d postgres -a -f sql/pre_indexes.sql
```

- **Create Grid Table** :
- **Create Grid Table**:

```
psql -h localhost -U admin -d postgres -a -f sql/grid.sql
```

- **Create Country Table** :
- **Create Country Table**:

```
psql -h localhost -U admin -d postgres -a -f sql/countries.sql
```

- **Apply Grid Update Script** :
There is grid_update script , Which is responsible for the Grid Column update on the tables which will be null intially when you import
- **Apply Grid Update Script**:
There is grid_update script, which is responsible for the Grid Column update on the tables which will be null intially when you import

**Run Script**

Expand Down Expand Up @@ -117,7 +117,7 @@ port=

## Initialize Update Script

Now run init , This will create replication status table in db
Now run init, this will create replication status table in db

> Export database password or keep it inside systemd service or pass W after command -- -W

Expand All @@ -131,7 +131,7 @@ Now Run update with lua script file location : _-s_ parameter like this (Conside
python replication update -s raw.lua --max-diff-size 10
```

with force password prompt (Only if you wish to supply pass from command) :
with force password prompt (Only if you wish to supply pass from command):

```
python replication update -s raw.lua -- -W
Expand All @@ -141,4 +141,4 @@ Read more documentation [here](https://osm2pgsql.org/doc/manual.html#advanced-to

## Configure Per Minute Replication

There are multiple options to run this python script per minute , You can either setup a cronjob or setup a systemd service
There are multiple options to run this python script per minute, you can either setup a cronjob or setup a systemd service
4 changes: 2 additions & 2 deletions docker-compose-config.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ CELERY_BROKER_URL=redis://redis:6379/0
CELERY_RESULT_BACKEND=redis://redis:6379/0

[OAUTH]
OSM_CLIENT_ID=
OSM_CLIENT_SECRET=
OSM_CLIENT_ID=LXHWp2bDOWGkKavZFK2UAewNgApRZ00qZzgsaT5Vrx0
OSM_CLIENT_SECRET=5NZ-8OATs7dpaewPtPP1-Ia7WCDrrp6x_isNRiIMnJk
OSM_URL=https://www.openstreetmap.org
OSM_PERMISSION_SCOPE=read_prefs
LOGIN_REDIRECT_URI=http://127.0.0.1:8000/v1/auth/callback
Expand Down
Loading