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_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)]
|
||||
) -> list[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)
|
||||
data = await db_session.exec(select(UserRoleLink))
|
||||
return data.all() # type: ignore[return-value]
|
||||
|
|
|
@ -5,7 +5,7 @@ from asyncio import sleep
|
|||
import logging
|
||||
|
||||
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.sql.selectable import Select
|
||||
from sqlmodel import SQLModel, select, func, col
|
||||
|
@ -163,6 +163,8 @@ async def create_db(drop=False):
|
|||
attempts = CREATE_DB_TIMEOUT
|
||||
|
||||
async def try_once():
|
||||
async with engine.begin() as conn:
|
||||
await create_schemas(conn)
|
||||
async with engine.begin() as conn:
|
||||
if drop:
|
||||
await conn.run_sync(SQLModel.metadata.drop_all)
|
||||
|
@ -199,14 +201,30 @@ async def is_fresh_install() -> bool:
|
|||
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():
|
||||
"""Populate the database for a fresh install"""
|
||||
from sqlalchemy import text
|
||||
from gisaf.security import create_user # , add_role, add_user_role
|
||||
from gisaf.security import create_user, create_role, add_user_role
|
||||
from gisaf.models.map_bases import BaseStyle
|
||||
|
||||
logger.info("Populating initial database")
|
||||
|
||||
async with db_session() as session:
|
||||
|
||||
user = await create_user(
|
||||
session=session,
|
||||
username="admin",
|
||||
|
@ -215,10 +233,15 @@ async def populate_init_db():
|
|||
email="root@localhost.localdomain",
|
||||
active=True,
|
||||
)
|
||||
assert user is not None
|
||||
# role = await add_role(role_id="admin")
|
||||
# await add_user_role(user.username, role.name)
|
||||
# for initial in initials:
|
||||
# await session.execute(text(initial))
|
||||
# logger.debug(f"Added map style {initial}")
|
||||
# await session.commit()
|
||||
role = await create_role(
|
||||
session, name="admin", description="Initial admin user"
|
||||
)
|
||||
await session.refresh(user)
|
||||
await session.refresh(role)
|
||||
await add_user_role(session, user, role)
|
||||
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)
|
||||
name: str
|
||||
style: dict[str, Any] | None = Field(sa_type=JSON(none_as_null=True)) # type: ignore
|
||||
mbtiles: str = Field(sa_type=String(50)) # type: ignore
|
||||
static_tiles_url: str
|
||||
style: dict[str, Any] | None = Field(sa_type=JSON(none_as_null=True), default=None)
|
||||
mbtiles: str | None = Field(sa_type=String(50), default=None)
|
||||
static_url: str | None = Field(sa_type=String(250), default=None)
|
||||
enabled: bool = True
|
||||
|
||||
def __repr__(self):
|
||||
|
|
|
@ -15,7 +15,7 @@ from sqlalchemy.orm import selectinload
|
|||
|
||||
from gisaf.config import conf
|
||||
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__)
|
||||
|
||||
|
@ -97,6 +97,38 @@ async def create_user(
|
|||
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:
|
||||
query = (
|
||||
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()
|
||||
|
||||
|
||||
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):
|
||||
try:
|
||||
return pwd_context.verify(plain_password, user.password)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue