19 Commits

Author SHA1 Message Date
b6c33534f1 rental objects 2021-07-05 18:27:59 +02:00
67c97ed4bc add tenant, fix 2021-07-05 12:04:22 +02:00
81ba2655b3 add tenant 2021-07-05 12:03:56 +02:00
1e9d22483c tenant 2021-07-05 10:25:08 +02:00
daca7eca9b db refactoring, one and many 2021-07-02 14:52:07 +02:00
32a66dc189 dbconfig 2021-07-02 11:08:55 +02:00
3dd00d6dcd db in account 2021-07-02 11:02:08 +02:00
44b58bc48c db in account 2021-07-02 10:53:42 +02:00
1bddff4a23 add first get method 2021-07-01 19:37:24 +02:00
b500b81d80 fix ci script 2021-07-01 16:21:25 +02:00
5937c99eb4 change testoutput format 2021-06-17 19:10:18 +02:00
dfc5c8421a change testoutput format 2021-06-17 19:05:35 +02:00
b30e587c34 change testoutput format 2021-06-17 19:01:12 +02:00
3d0e602ee6 adjust header of openapi.yml, fix 2021-06-17 12:52:05 +02:00
30aa514495 adjust header of openapi.yml, fix 2021-06-17 12:34:25 +02:00
c72d9bc5ae adjust header of openapi.yml, fix 2021-06-17 12:32:30 +02:00
b64d04c45a adjust header of openapi.yml 2021-06-17 12:30:07 +02:00
f826248b69 fix 2021-06-17 12:07:20 +02:00
8446c72c35 fix 2021-06-17 12:05:22 +02:00
9 changed files with 510 additions and 18 deletions

View File

@ -37,8 +37,6 @@ build:
docker push $IMAGE_NAME:${CI_COMMIT_TAG};
fi
deploy:
stage: deploy
image: registry.hottis.de/dockerized/docker-bash:latest
@ -56,7 +54,8 @@ deploy:
- SERVICE_PORT=5000
- docker volume inspect $SERVICE_VOLUME || docker volume create $SERVICE_VOLUME
- docker stop $CONTAINER_NAME || echo "$CONTAINER_NAME not running, anyway okay"
- docker rm $CONTAINER_NAME || echo "$CONTAINER_NAME not exsting, anyway okay"
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY;
- docker pull $IMAGE_NAME:${CI_COMMIT_TAG}
- docker run -d --restart always --name "hv2-api" -p 5000:5000 -v $SERVICE_VOLUME:/opt/app/config $IMAGE_NAME:${CI_COMMIT_TAG}
- docker run -d --restart always --name $CONTAINER_NAME --network docker-server --ip 172.16.10.38 -v $SERVICE_VOLUME:/opt/app/config $IMAGE_NAME:${CI_COMMIT_TAG}

View File

@ -6,10 +6,6 @@ LABEL ImageName="registry.hottis.de/hv2/hv2-api"
ARG APP_DIR="/opt/app"
ARG CONF_DIR="${APP_DIR}/config"
ENV DB_HOST="172.16.10.18"
ENV DB_NAME="hausverwaltung"
ENV DB_USER="hausverwaltung-ui"
ENV DB_PASS="test123"
RUN \

View File

@ -1,2 +1,10 @@
# copy to ENV and adjust values
JWT_PUB_KEY="..."
DB_USER="hv2"
DB_PASS="..."
DB_HOST="172.16.10.27"
DB_NAME="hv2"

8
account.py Normal file
View File

@ -0,0 +1,8 @@
from db import dbGetMany, dbGetOne
def getAccounts(user, token_info):
return dbGetMany(user, token_info, {"statement": "SELECT id, description FROM account_t", "params": ()})
def getAccount(user, token_info, accountId=None):
return dbGetOne(user, token_info, {"statement": "select id, description from account_t where id = %s", "params": (accountId, )})

12
auth.py
View File

@ -2,7 +2,7 @@ from jose import JWTError, jwt
import werkzeug
import os
from loguru import logger
import json
JWT_PUB_KEY = ""
try:
@ -19,9 +19,9 @@ def decodeToken(token):
logger.error("{}".format(e))
raise werkzeug.exceptions.Unauthorized()
def testToken(user, token_info):
return '''
You are user_id {user} and the provided token has been signed by this issuers. Fine.'.
Decoded token claims: {token_info}.
'''.format(user=user, token_info=token_info)
def testToken(user, token_info):
return {
"message": f"You are user_id {user} and the provided token has been signed by this issuers. Fine.",
"details": json.dumps(token_info)
}

103
db.py Normal file
View File

@ -0,0 +1,103 @@
import psycopg2
import psycopg2.extras
from loguru import logger
import os
import configparser
import json
import werkzeug
DB_USER = ""
DB_PASS = ""
DB_HOST = ""
DB_NAME = ""
try:
DB_USER = os.environ["DB_USER"]
DB_PASS = os.environ["DB_PASS"]
DB_HOST = os.environ["DB_HOST"]
DB_NAME = os.environ["DB_NAME"]
except KeyError:
config = configparser.ConfigParser()
config.read('/opt/app/config/dbconfig.ini')
DB_USER = config["database"]["user"]
DB_PASS = config["database"]["pass"]
DB_HOST = config["database"]["host"]
DB_NAME = config["database"]["name"]
class NoDataFoundException(Exception): pass
class TooMuchDataFoundException(Exception): pass
def databaseOperation(cursor, params):
cursor.execute('SELECT key, value FROM claims_for_user_v where "user" = %s and application = %s',
params)
for claimObj in cursor:
logger.debug("add claim {} -> {}".format(claimObj[0], claimObj[1]))
return []
def execDatabaseOperation(func, params):
conn = None
cur = None
try:
conn = psycopg2.connect(user = DB_USER, password = DB_PASS,
host = DB_HOST, database = DB_NAME,
sslmode = 'require')
conn.autocommit = False
with conn.cursor(cursor_factory = psycopg2.extras.RealDictCursor) as cur:
return func(cur, params)
except psycopg2.Error as err:
raise Exception("Error when connecting to database: {}".format(err))
finally:
if conn:
conn.close()
def _opGetMany(cursor, params):
items = []
cursor.execute(params["statement"])
for itemObj in cursor:
logger.debug("item received {}".format(str(itemObj)))
items.append(itemObj)
return items
def dbGetMany(user, token_info, params):
logger.info("params: {}, token: {}".format(params, json.dumps(token_info)))
try:
return execDatabaseOperation(_opGetMany, params)
except Exception as e:
logger.error(f"Exception: {e}")
raise werkzeug.exceptions.InternalServerError
def _opGetOne(cursor, params):
cursor.execute(params["statement"], params["params"])
itemObj = cursor.fetchone()
logger.debug(f"item received: {itemObj}")
if not itemObj:
raise NoDataFoundException
dummyObj = cursor.fetchone()
if dummyObj:
raise TooMuchDataFoundException
return itemObj
def dbGetOne(user, token_info, params):
logger.info("params: {}, token: {}".format(params, json.dumps(token_info)))
try:
return execDatabaseOperation(_opGetOne, params)
except NoDataFoundException:
logger.error("no data found")
raise werkzeug.exceptions.NotFound
except TooMuchDataFoundException:
logger.error("too much data found")
raise werkzeug.exceptions.InternalServerError
except Exception as e:
logger.error(f"Exception: {e}")
raise werkzeug.exceptions.InternalServerError

View File

@ -1,10 +1,18 @@
openapi: 3.0.0
info:
title: hv2-api
version: "0.1"
version: "1"
description: "REST-API for the Nober Grundbesitz GbR Hausverwaltungs-Software"
termsOfService: "https://home.hottis.de/dokuwiki/doku.php?id=hv2pub:termsofuse"
contact:
name: "Wolfgang Hottgenroth"
email: "wolfgang.hottgenroth@icloud.com"
externalDocs:
description: "Find more details here"
url: "https://home.hottis.de/dokuwiki/doku.php?id=hv2pub:externaldocs"
paths:
/test:
/v1/test:
get:
tags: [ "Test" ]
summary: Return secret string
@ -13,12 +21,201 @@ paths:
'200':
description: secret response
content:
'text/plain':
'application/json':
schema:
type: string
$ref: '#/components/schemas/TestOutput'
security:
- jwt: ['secret']
/v1/accounts:
get:
tags: [ "Account" ]
summary: Return all normalized accounts
operationId: account.getAccounts
responses:
'200':
description: accounts response
content:
'application/json':
schema:
type: array
items:
$ref: '#/components/schemas/Account'
security:
- jwt: ['secret']
/v1/accounts/{accountId}:
get:
tags: [ "Account" ]
summary: Return the normalized account with given id
operationId: account.getAccount
parameters:
- name: accountId
in: path
required: true
schema:
type: integer
responses:
'200':
description: accounts response
content:
'application/json':
schema:
type: array
items:
$ref: '#/components/schemas/Account'
security:
- jwt: ['secret']
/v1/tenants:
get:
tags: [ "Tenant" ]
summary: Return all normalized tenants
operationId: tenant.getTenants
responses:
'200':
description: tenant response
content:
'application/json':
schema:
type: array
items:
$ref: '#/components/schemas/Tenant'
security:
- jwt: ['secret']
/v1/tenants/{tenantId}:
get:
tags: [ "Tenant" ]
summary: Return the normalized tenant with given id
operationId: tenant.getTenant
parameters:
- name: tenantId
in: path
required: true
schema:
type: integer
responses:
'200':
description: tenants response
content:
'application/json':
schema:
type: array
items:
$ref: '#/components/schemas/Tenant'
security:
- jwt: ['secret']
/v1/commercialPremises:
get:
tags: [ "CommercialPremise" ]
summary: Return all normalized commercial premises
operationId: rentalObjects.getCommercialPremises
responses:
'200':
description: commercial premise response
content:
'application/json':
schema:
type: array
items:
$ref: '#/components/schemas/CommercialPremise'
security:
- jwt: ['secret']
/v1/commercialPremises/{commercialPremiseId}:
get:
tags: [ "CommercialPremise" ]
summary: Return the normalized commercial premise with given id
operationId: rentalObjects.getCommercialPremise
parameters:
- name: commercialPremiseId
in: path
required: true
schema:
type: integer
responses:
'200':
description: commercial premise response
content:
'application/json':
schema:
type: array
items:
$ref: '#/components/schemas/CommercialPremise'
security:
- jwt: ['secret']
/v1/parkings:
get:
tags: [ "Parking" ]
summary: Return all normalized parkings
operationId: rentalObjects.getParkings
responses:
'200':
description: parkings response
content:
'application/json':
schema:
type: array
items:
$ref: '#/components/schemas/Parking'
security:
- jwt: ['secret']
/v1/parkings/{parkingId}:
get:
tags: [ "Parking" ]
summary: Return the normalized parking with given id
operationId: rentalObjects.getParking
parameters:
- name: parkingId
in: path
required: true
schema:
type: integer
responses:
'200':
description: parking response
content:
'application/json':
schema:
type: array
items:
$ref: '#/components/schemas/Parking'
security:
- jwt: ['secret']
/v1/flats:
get:
tags: [ "Flat" ]
summary: Return all normalized flats
operationId: rentalObjects.getFlats
responses:
'200':
description: flat response
content:
'application/json':
schema:
type: array
items:
$ref: '#/components/schemas/Flat'
security:
- jwt: ['secret']
/v1/flats/{flatId}:
get:
tags: [ "Flat" ]
summary: Return the normalized flat with given id
operationId: rentalObjects.getFlat
parameters:
- name: flatId
in: path
required: true
schema:
type: integer
responses:
'200':
description: flat response
content:
'application/json':
schema:
type: array
items:
$ref: '#/components/schemas/Flat'
security:
- jwt: ['secret']
components:
securitySchemes:
@ -27,3 +224,84 @@ components:
scheme: bearer
bearerFormat: JWT
x-bearerInfoFunc: auth.decodeToken
schemas:
TestOutput:
description: Test Output
type: object
properties:
message:
type: string
details:
type: string
Account:
description: Account
type: object
properties:
id:
type: integer
description:
type: string
Tenant:
description: Tenant
type: object
properties:
id:
type: integer
salutation:
type: string
firstname:
type: string
lastname:
type: string
address1:
type: string
address2:
type: string
address3:
type: string
zip:
type: string
city:
type: string
phone1:
type: string
phone2:
type: string
iban:
type: string
account:
type: integer
CommercialPremise:
description: CommercialPremise
type: object
properties:
id:
type: integer
description:
type: string
premise:
type: integer
Parking:
description: Parking
type: object
properties:
id:
type: integer
description:
type: string
premise:
type: integer
Flat:
description: Flat
type: object
properties:
id:
type: integer
description:
type: string
premise:
type: integer
area:
type: number
flat_no:
type: integer

71
rentalObjects.py Normal file
View File

@ -0,0 +1,71 @@
from db import dbGetMany, dbGetOne
def getCommercialPremises(user, token_info):
return dbGetMany(user, token_info,
{
"statement": """
SELECT id, description, premise
FROM commercial_premise_t
""",
"params": ()
}
)
def getCommercialPremise(user, token_info, commercialPremiseId=None):
return dbGetOne(user, token_info,
{
"statement": """
SELECT id, description, premise
FROM commercial_premise_t
WHERE id = %s
""",
"params": (commercialPremiseId, )
}
)
def getFlats(user, token_info):
return dbGetMany(user, token_info,
{
"statement": """
SELECT id, description, premise, area, flat_no
FROM flat_t
""",
"params": ()
}
)
def getFlat(user, token_info, flatId=None):
return dbGetOne(user, token_info,
{
"statement": """
SELECT id, description, premise, area, flat_no
FROM flat_t
WHERE id = %s
""",
"params": (flatId, )
}
)
def getParking(user, token_info):
return dbGetMany(user, token_info,
{
"statement": """
SELECT id, description, premise
FROM parking_t
""",
"params": ()
}
)
def getParking(user, token_info, parkingId=None):
return dbGetOne(user, token_info,
{
"statement": """
SELECT id, description, premise
FROM parking_t
WHERE id = %s
""",
"params": (parkingId, )
}
)

29
tenant.py Normal file
View File

@ -0,0 +1,29 @@
from db import dbGetMany, dbGetOne
def getTenants(user, token_info):
return dbGetMany(user, token_info,
{
"statement": """
SELECT id, salutation, firstname, lastname,
address1, address2, address3, zip, city,
phone1, phone2, iban, account
FROM tenant_t
""",
"params": ()
}
)
def getTenant(user, token_info, tenantId=None):
return dbGetOne(user, token_info,
{
"statement": """
SELECT id, salutation, firstname, lastname,
address1, address2, address3, zip, city,
phone1, phone2, iban, account
FROM tenant_t
WHERE id = %s
""",
"params": (tenantId, )
}
)