Initdb: create database schemas, admin role, initial background map
All checks were successful
/ test (push) Successful in 32s
All checks were successful
/ test (push) Successful in 32s
This commit is contained in:
parent
e44911db8e
commit
7354b9bab8
6 changed files with 76 additions and 47 deletions
|
@ -2,6 +2,3 @@ FROM docker.io/postgis/postgis:17-3.5-alpine
|
||||||
|
|
||||||
ENV POSTGRES_USER gisaf
|
ENV POSTGRES_USER gisaf
|
||||||
ENV POSTGRES_PASSWORD secret
|
ENV POSTGRES_PASSWORD secret
|
||||||
|
|
||||||
# Overwrite standard postgis entrypoint
|
|
||||||
COPY ./database-container-entrypoint-postgis.sh /docker-entrypoint-initdb.d/10_postgis.sh
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Perform all actions as $POSTGRES_USER
|
|
||||||
export PGUSER="$POSTGRES_USER"
|
|
||||||
|
|
||||||
# Create the 'template_postgis' template db
|
|
||||||
"${psql[@]}" <<-'EOSQL'
|
|
||||||
CREATE DATABASE template_postgis IS_TEMPLATE true;
|
|
||||||
EOSQL
|
|
||||||
|
|
||||||
# Load PostGIS into both template_database and $POSTGRES_DB
|
|
||||||
for DB in template_postgis "$POSTGRES_DB"; do
|
|
||||||
echo "Loading PostGIS extensions into $DB"
|
|
||||||
"${psql[@]}" --dbname="$DB" <<-'EOSQL'
|
|
||||||
CREATE EXTENSION IF NOT EXISTS postgis;
|
|
||||||
EOSQL
|
|
||||||
done
|
|
||||||
|
|
||||||
"${psql[@]}" --dbname="$DB" <<-'EOSQL'
|
|
||||||
CREATE EXTENSION IF NOT EXISTS hstore;
|
|
||||||
CREATE SCHEMA gisaf;
|
|
||||||
CREATE SCHEMA gisaf_admin;
|
|
||||||
CREATE SCHEMA gisaf_map;
|
|
||||||
CREATE SCHEMA gisaf_survey;
|
|
||||||
CREATE SCHEMA raw_survey;
|
|
||||||
CREATE SCHEMA survey;
|
|
||||||
EOSQL
|
|
|
@ -115,7 +115,7 @@ async def get_acls(
|
||||||
db_session: db_session, user: Annotated[User, Depends(get_current_active_user)]
|
db_session: db_session, user: Annotated[User, Depends(get_current_active_user)]
|
||||||
) -> list[UserRoleLink]:
|
) -> list[UserRoleLink]:
|
||||||
"""New: ACLs returned as UserRoleLink"""
|
"""New: ACLs returned as UserRoleLink"""
|
||||||
if user is not None or not user.has_role("manager"):
|
if user is None or not user.has_role("manager"):
|
||||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
|
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
|
||||||
data = await db_session.exec(select(UserRoleLink))
|
data = await db_session.exec(select(UserRoleLink))
|
||||||
return data.all() # type: ignore[return-value]
|
return data.all() # type: ignore[return-value]
|
||||||
|
|
|
@ -5,7 +5,7 @@ from asyncio import sleep
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from sqlalchemy.ext.asyncio import create_async_engine
|
from sqlalchemy.ext.asyncio import create_async_engine
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine, text
|
||||||
from sqlalchemy.orm import joinedload, QueryableAttribute
|
from sqlalchemy.orm import joinedload, QueryableAttribute
|
||||||
from sqlalchemy.sql.selectable import Select
|
from sqlalchemy.sql.selectable import Select
|
||||||
from sqlmodel import SQLModel, select, func, col
|
from sqlmodel import SQLModel, select, func, col
|
||||||
|
@ -163,6 +163,8 @@ async def create_db(drop=False):
|
||||||
attempts = CREATE_DB_TIMEOUT
|
attempts = CREATE_DB_TIMEOUT
|
||||||
|
|
||||||
async def try_once():
|
async def try_once():
|
||||||
|
async with engine.begin() as conn:
|
||||||
|
await create_schemas(conn)
|
||||||
async with engine.begin() as conn:
|
async with engine.begin() as conn:
|
||||||
if drop:
|
if drop:
|
||||||
await conn.run_sync(SQLModel.metadata.drop_all)
|
await conn.run_sync(SQLModel.metadata.drop_all)
|
||||||
|
@ -199,14 +201,30 @@ async def is_fresh_install() -> bool:
|
||||||
return nb_users == 0
|
return nb_users == 0
|
||||||
|
|
||||||
|
|
||||||
|
async def create_schemas(conn):
|
||||||
|
"""Create schemas and extensions"""
|
||||||
|
raw_sql = [
|
||||||
|
"CREATE EXTENSION IF NOT EXISTS hstore",
|
||||||
|
"CREATE SCHEMA IF NOT EXISTS gisaf",
|
||||||
|
"CREATE SCHEMA IF NOT EXISTS gisaf_admin",
|
||||||
|
"CREATE SCHEMA IF NOT EXISTS gisaf_map",
|
||||||
|
"CREATE SCHEMA IF NOT EXISTS gisaf_survey",
|
||||||
|
"CREATE SCHEMA IF NOT EXISTS raw_survey",
|
||||||
|
"CREATE SCHEMA IF NOT EXISTS survey",
|
||||||
|
]
|
||||||
|
for rs in raw_sql:
|
||||||
|
await conn.execute(text(rs))
|
||||||
|
|
||||||
|
|
||||||
async def populate_init_db():
|
async def populate_init_db():
|
||||||
"""Populate the database for a fresh install"""
|
"""Populate the database for a fresh install"""
|
||||||
from sqlalchemy import text
|
from gisaf.security import create_user, create_role, add_user_role
|
||||||
from gisaf.security import create_user # , add_role, add_user_role
|
from gisaf.models.map_bases import BaseStyle
|
||||||
|
|
||||||
logger.info("Populating initial database")
|
logger.info("Populating initial database")
|
||||||
|
|
||||||
async with db_session() as session:
|
async with db_session() as session:
|
||||||
|
|
||||||
user = await create_user(
|
user = await create_user(
|
||||||
session=session,
|
session=session,
|
||||||
username="admin",
|
username="admin",
|
||||||
|
@ -215,10 +233,15 @@ async def populate_init_db():
|
||||||
email="root@localhost.localdomain",
|
email="root@localhost.localdomain",
|
||||||
active=True,
|
active=True,
|
||||||
)
|
)
|
||||||
assert user is not None
|
role = await create_role(
|
||||||
# role = await add_role(role_id="admin")
|
session, name="admin", description="Initial admin user"
|
||||||
# await add_user_role(user.username, role.name)
|
)
|
||||||
# for initial in initials:
|
await session.refresh(user)
|
||||||
# await session.execute(text(initial))
|
await session.refresh(role)
|
||||||
# logger.debug(f"Added map style {initial}")
|
await add_user_role(session, user, role)
|
||||||
# await session.commit()
|
openFreeMap = BaseStyle(
|
||||||
|
name="OpenFreeMap",
|
||||||
|
static_url="https://tiles.openfreemap.org/styles/liberty",
|
||||||
|
)
|
||||||
|
session.add(openFreeMap)
|
||||||
|
await session.commit()
|
||||||
|
|
|
@ -19,9 +19,9 @@ class BaseStyle(Model, table=True):
|
||||||
|
|
||||||
id: int | None = Field(primary_key=True, default=None)
|
id: int | None = Field(primary_key=True, default=None)
|
||||||
name: str
|
name: str
|
||||||
style: dict[str, Any] | None = Field(sa_type=JSON(none_as_null=True)) # type: ignore
|
style: dict[str, Any] | None = Field(sa_type=JSON(none_as_null=True), default=None)
|
||||||
mbtiles: str = Field(sa_type=String(50)) # type: ignore
|
mbtiles: str | None = Field(sa_type=String(50), default=None)
|
||||||
static_tiles_url: str
|
static_url: str | None = Field(sa_type=String(250), default=None)
|
||||||
enabled: bool = True
|
enabled: bool = True
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
|
|
@ -15,7 +15,7 @@ from sqlalchemy.orm import selectinload
|
||||||
|
|
||||||
from gisaf.config import conf
|
from gisaf.config import conf
|
||||||
from gisaf.database import db_session
|
from gisaf.database import db_session
|
||||||
from gisaf.models.authentication import User, UserRead
|
from gisaf.models.authentication import User, UserRead, Role, UserRoleLink
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -97,6 +97,38 @@ async def create_user(
|
||||||
return user_in_db
|
return user_in_db
|
||||||
|
|
||||||
|
|
||||||
|
async def create_role(
|
||||||
|
session: AsyncSession,
|
||||||
|
name: str,
|
||||||
|
description: str | None = None,
|
||||||
|
):
|
||||||
|
role_in_db = await get_role(session, name)
|
||||||
|
if role_in_db is None:
|
||||||
|
role = Role(
|
||||||
|
name=name,
|
||||||
|
description=description,
|
||||||
|
)
|
||||||
|
session.add(role)
|
||||||
|
await session.commit()
|
||||||
|
return role
|
||||||
|
else:
|
||||||
|
role_in_db.description = description
|
||||||
|
await session.commit()
|
||||||
|
return role_in_db
|
||||||
|
|
||||||
|
|
||||||
|
async def add_user_role(session: AsyncSession, user: User, role: Role) -> User | None:
|
||||||
|
query = select(UserRoleLink).where(
|
||||||
|
UserRoleLink.user_id == user.id, UserRoleLink.role_id == role.id
|
||||||
|
)
|
||||||
|
data = await session.exec(query)
|
||||||
|
user_role = data.one_or_none()
|
||||||
|
if user_role is None:
|
||||||
|
user_role = UserRoleLink(user_id=user.id, role_id=role.id)
|
||||||
|
session.add(user_role)
|
||||||
|
await session.commit()
|
||||||
|
|
||||||
|
|
||||||
async def get_user(session: AsyncSession, username: str) -> User | None:
|
async def get_user(session: AsyncSession, username: str) -> User | None:
|
||||||
query = (
|
query = (
|
||||||
select(User).where(User.username == username).options(selectinload(User.roles))
|
select(User).where(User.username == username).options(selectinload(User.roles))
|
||||||
|
@ -105,6 +137,12 @@ async def get_user(session: AsyncSession, username: str) -> User | None:
|
||||||
return data.one_or_none()
|
return data.one_or_none()
|
||||||
|
|
||||||
|
|
||||||
|
async def get_role(session: AsyncSession, name: str) -> Role | None:
|
||||||
|
query = select(Role).where(Role.name == name)
|
||||||
|
data = await session.exec(query)
|
||||||
|
return data.one_or_none()
|
||||||
|
|
||||||
|
|
||||||
def verify_password(user: User, plain_password):
|
def verify_password(user: User, plain_password):
|
||||||
try:
|
try:
|
||||||
return pwd_context.verify(plain_password, user.password)
|
return pwd_context.verify(plain_password, user.password)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue