Hello community, here is the log from the commit of package gnuhealth-thalamus for openSUSE:Factory checked in at 2019-03-11 11:15:19 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/gnuhealth-thalamus (Old) and /work/SRC/openSUSE:Factory/.gnuhealth-thalamus.new.28833 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "gnuhealth-thalamus" Mon Mar 11 11:15:19 2019 rev:2 rq:682998 version:0.9.8 Changes: -------- --- /work/SRC/openSUSE:Factory/gnuhealth-thalamus/gnuhealth-thalamus.changes 2019-02-01 11:44:07.736633616 +0100 +++ /work/SRC/openSUSE:Factory/.gnuhealth-thalamus.new.28833/gnuhealth-thalamus.changes 2019-03-11 11:15:27.069338510 +0100 @@ -1,0 +2,6 @@ +Fri Mar 8 20:57:13 UTC 2019 - Axel Braun <axel.br...@gmx.de> + +- Version 0.9.8 + rewrite to use PostgreSQL instad of mongoDB + +------------------------------------------------------------------- Old: ---- thalamus-0.9.5.tar.gz New: ---- _service thalamus-0.9.8.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ gnuhealth-thalamus.spec ++++++ --- /var/tmp/diff_new_pack.8DAVIk/_old 2019-03-11 11:15:29.345337692 +0100 +++ /var/tmp/diff_new_pack.8DAVIk/_new 2019-03-11 11:15:29.389337677 +0100 @@ -1,8 +1,8 @@ # # spec file for package gnuhealth-thalamus # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. -# Copyright (c) 2017-218 Dr. Axel Braun +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2017-2019 Dr. Axel Braun # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -13,35 +13,41 @@ # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. -# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# + %bcond_without test %define modname thalamus Name: gnuhealth-%{modname} -Version: 0.9.5 +Version: 0.9.8 Release: 0 -License: GPL-3.0-or-later Summary: The GNU Health Federation Message and Authentication Server -Url: http://health.gnu.org +License: GPL-3.0-or-later Group: Development/Languages/Python +Url: http://health.gnu.org Source: https://files.pythonhosted.org/packages/source/t/%{modname}/%{modname}-%{version}.tar.gz +BuildRequires: postgresql-server BuildRequires: python-rpm-macros BuildRequires: python3-devel BuildRequires: python3-setuptools %if %{with test} -BuildRequires: python3-bcrypt BuildRequires: python3-Flask BuildRequires: python3-Flask-HTTPAuth -BuildRequires: python3-Flask-PyMongo BuildRequires: python3-Flask-RESTful +BuildRequires: python3-Flask-WTF +BuildRequires: python3-bcrypt +BuildRequires: python3-psycopg2 %endif BuildRequires: fdupes -Requires: python3-bcrypt +Requires: postgresql-server Requires: python3-Flask Requires: python3-Flask-HTTPAuth -Requires: python3-Flask-PyMongo Requires: python3-Flask-RESTful +Requires: python3-Flask-WTF +Requires: python3-bcrypt +Requires: python3-psycopg2 BuildArch: noarch %description ++++++ _service ++++++ <services> <service name="download_files" mode="localonly" /> </services> ++++++ thalamus-0.9.5.tar.gz -> thalamus-0.9.8.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/thalamus-0.9.5/MANIFEST.in new/thalamus-0.9.8/MANIFEST.in --- old/thalamus-0.9.5/MANIFEST.in 2018-12-16 13:55:41.000000000 +0100 +++ new/thalamus-0.9.8/MANIFEST.in 2019-03-08 17:09:09.000000000 +0100 @@ -4,9 +4,12 @@ global-include *.html global-include *.css -include demo/*.json -include demo/populate.sh -inclue doc/*.rst +include thalamus/demo/*.json +include thalamus/demo/populate.sh +include thalamus/demo/federation_schema.sql +include thalamus/demo/ana_newborn.jpg + +include thalamus/doc/*.rst include MANIFEST.in include LICENSE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/thalamus-0.9.5/PKG-INFO new/thalamus-0.9.8/PKG-INFO --- old/thalamus-0.9.5/PKG-INFO 2018-12-16 14:32:13.000000000 +0100 +++ new/thalamus-0.9.8/PKG-INFO 2019-03-08 17:26:43.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: thalamus -Version: 0.9.5 +Version: 0.9.8 Summary: The GNU Health Federation Message and Authentication Server Home-page: http://health.gnu.org Author: GNU Solidario @@ -15,7 +15,7 @@ #. **Message server**: A concentrator and message relay from and to the participating nodes in the GNU Health Federation and the GNU Health - Information System (MongoDB). Some of the participating nodes include + Information System (PgSQL). Some of the participating nodes include the GNU Health HMIS, MyGNUHealth mobile PHR application, laboratories, research institutions and civil offices. @@ -65,6 +65,8 @@ * DomiciliaryUnits (/domiciliary-units) + * PersonalDocs (/personal_docs) + Running Thalamus from a WSGI Container -------------------------------------- In production settings, for performance reasons you should use a HTTP server. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/thalamus-0.9.5/README.rst new/thalamus-0.9.8/README.rst --- old/thalamus-0.9.5/README.rst 2018-11-27 00:07:32.000000000 +0100 +++ new/thalamus-0.9.8/README.rst 2019-03-08 14:39:36.000000000 +0100 @@ -6,7 +6,7 @@ #. **Message server**: A concentrator and message relay from and to the participating nodes in the GNU Health Federation and the GNU Health - Information System (MongoDB). Some of the participating nodes include + Information System (PgSQL). Some of the participating nodes include the GNU Health HMIS, MyGNUHealth mobile PHR application, laboratories, research institutions and civil offices. @@ -56,6 +56,8 @@ * DomiciliaryUnits (/domiciliary-units) +* PersonalDocs (/personal_docs) + Running Thalamus from a WSGI Container -------------------------------------- In production settings, for performance reasons you should use a HTTP server. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/thalamus-0.9.5/requirements.txt new/thalamus-0.9.8/requirements.txt --- old/thalamus-0.9.5/requirements.txt 2018-12-16 12:42:37.000000000 +0100 +++ new/thalamus-0.9.8/requirements.txt 2019-03-08 15:57:36.000000000 +0100 @@ -1,6 +1,6 @@ flask flask_httpauth flask_restful -flask_pymongo flask_wtf +psycopg2 bcrypt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/thalamus-0.9.5/setup.py new/thalamus-0.9.8/setup.py --- old/thalamus-0.9.5/setup.py 2018-12-16 12:39:35.000000000 +0100 +++ new/thalamus-0.9.8/setup.py 2019-03-08 15:58:18.000000000 +0100 @@ -8,8 +8,8 @@ # ############################################################################## # -# Copyright (C) 2008 - 2018 Luis Falcon <lfal...@gnusolidario.org> -# Copyright (C) 2008 - 2018 GNU Solidario <hea...@gnusolidario.org> +# Copyright (C) 2008 - 2019 Luis Falcon <lfal...@gnusolidario.org> +# Copyright (C) 2008 - 2019 GNU Solidario <hea...@gnusolidario.org> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -59,8 +59,8 @@ "flask", "flask_httpauth", "flask_restful", - "flask_pymongo", "flask_wtf", + "psycopg2", "bcrypt", ], packages=find_packages(), Binary files old/thalamus-0.9.5/thalamus/demo/ana_newborn.jpg and new/thalamus-0.9.8/thalamus/demo/ana_newborn.jpg differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/thalamus-0.9.5/thalamus/demo/federation_schema.sql new/thalamus-0.9.8/thalamus/demo/federation_schema.sql --- old/thalamus-0.9.5/thalamus/demo/federation_schema.sql 1970-01-01 01:00:00.000000000 +0100 +++ new/thalamus-0.9.8/thalamus/demo/federation_schema.sql 2019-03-08 14:36:35.000000000 +0100 @@ -0,0 +1,30 @@ +/* People table */ +CREATE TABLE IF NOT EXISTS people ( + id varchar PRIMARY KEY, + data jsonb + ); + +/* Page of Life */ +CREATE TABLE IF NOT EXISTS pols ( + id varchar PRIMARY KEY, + book varchar REFERENCES people (id), + data jsonb + ); + +/* Personal Documents */ +CREATE TABLE IF NOT EXISTS personal_docs ( + id varchar PRIMARY KEY, + fedacct varchar REFERENCES people (id), + pol varchar REFERENCES pols (id), + document bytea, + data jsonb); + +/* Domiciliary Units */ +CREATE TABLE IF NOT EXISTS dus ( + id varchar PRIMARY KEY, + data jsonb); + +/* Institutions */ +CREATE TABLE IF NOT EXISTS institutions ( + id varchar PRIMARY KEY, + data jsonb); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/thalamus-0.9.5/thalamus/demo/import_pg.py new/thalamus-0.9.8/thalamus/demo/import_pg.py --- old/thalamus-0.9.5/thalamus/demo/import_pg.py 1970-01-01 01:00:00.000000000 +0100 +++ new/thalamus-0.9.8/thalamus/demo/import_pg.py 2019-03-08 14:38:22.000000000 +0100 @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +import json +import sys +import psycopg2 + +#Modify to meet your needs +PG_URI = "postgresql://localhost/federation" + +try: + conn = psycopg2.connect(PG_URI) +except: + print ("Unable to connect to the database") + +people_file = open('people.json', 'r') +people_data = json.load(people_file) + +pols_file = open('pols.json', 'r') +pols_data = json.load(pols_file) + +personal_docs_file = open('personal_docs.json', 'r') +personal_docs_data = json.load(personal_docs_file) + + +doc_file = open('ana_newborn.jpg', 'rb') +document = doc_file.read() + + +doc_id = "8789981f-4e31-48d5-8eb8-1774dac8b8f6" +cur = conn.cursor() + + +for person in people_data: + id = person['id'] + print ("Inserting", id) + cur.execute("INSERT INTO people (ID, DATA) VALUES (%(id)s, \ + %(data)s)", {'id': id, 'data':json.dumps(person)}) + conn.commit() + + +for pol in pols_data: + id = pol['id'] + book = pol['book'] + print ("Inserting", id, book) + cur.execute("INSERT INTO pols (ID, BOOK, DATA) VALUES (%(id)s, \ + %(book)s, %(data)s)", {'id': id, 'book': book, 'data':json.dumps(pol)}) + conn.commit() + + +# Insert personal document for Ana Betz +for doc in personal_docs_data: + print ("Importing PERSONAL DOCS...", doc) + id = doc['id'] + fedacct = doc['fedacct'] + pol = doc['pol'] + cur.execute("INSERT INTO personal_docs \ + (ID, FEDACCT, POL, DATA) VALUES \ + (%(id)s, %(fedacct)s, %(pol)s, %(data)s \ + )", \ + {'id': id, 'fedacct': fedacct, 'pol': pol, 'data':json.dumps(doc)}) + conn.commit() + + +# Update specific personal doc from Ana newborn picture +cur.execute("UPDATE personal_docs SET document = %s where id = %s", \ + (document,doc_id)) +conn.commit() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/thalamus-0.9.5/thalamus/demo/people.json new/thalamus-0.9.8/thalamus/demo/people.json --- old/thalamus-0.9.5/thalamus/demo/people.json 1970-01-01 01:00:00.000000000 +0100 +++ new/thalamus-0.9.8/thalamus/demo/people.json 2019-03-08 14:33:31.000000000 +0100 @@ -0,0 +1,30 @@ +[ +{ +"id": "ITAPYT999HON", +"lastname": "Cordara", +"name": "Cameron", +"gender": "f", +"dob": "1984-10-05", +"marital_status":"married", +"ethnicity":"latino", +"education":"tertiary", +"profession":"teacher", +"password": "$2b$12$Y9rX7PoTHRXhTO1H78Tan.8mVmyayGAUIveiYxu2Qeo0ZDRvJQ8/2", +"roles":["end_user","health_professional"], +"active": true +}, +{ +"id": "ESPGNU777ORG", +"lastname": "Betz", +"name": "Ana", +"gender": "f", +"dob": "1985-10-04", +"marital_status":"married", +"ethnicity":"latino", +"education":"tertiary", +"profession":"teacher", +"password": "$2b$12$cjrKVGYEKUwCmVDCtEnwcegcrmECTmeBz526AAD/ZqMGPWFpHJ4FW", +"roles":["end_user"], +"active": true +} +] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/thalamus-0.9.5/thalamus/demo/personal_docs.json new/thalamus-0.9.8/thalamus/demo/personal_docs.json --- old/thalamus-0.9.5/thalamus/demo/personal_docs.json 1970-01-01 01:00:00.000000000 +0100 +++ new/thalamus-0.9.8/thalamus/demo/personal_docs.json 2019-03-08 14:37:17.000000000 +0100 @@ -0,0 +1,13 @@ +[ +{ +"id": "8789981f-4e31-48d5-8eb8-1774dac8b8f6", +"fedacct": "ESPGNU777ORG", +"pol": "119b352e-8e4f-4847-9f05-53462cf94f10", +"type": "picture", +"extension": "jpg", +"context": "identification", +"description":"Picture at birth", +"hash":"d11ce4d8d52cb70e2eb56e74a00eb2ada75b4e6885089d1213b80e8e87b105e4a8e27552ea9203698d10cc3fb08445f7968d6b1a96389ccff16f766d29f81b31", +"active": true +} +] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/thalamus-0.9.5/thalamus/demo/pols.json new/thalamus-0.9.8/thalamus/demo/pols.json --- old/thalamus-0.9.5/thalamus/demo/pols.json 1970-01-01 01:00:00.000000000 +0100 +++ new/thalamus-0.9.8/thalamus/demo/pols.json 2019-03-08 14:37:53.000000000 +0100 @@ -0,0 +1,29 @@ +[ +{ +"id": "119b352e-8e4f-4847-9f05-53462cf94f10", +"book": "ESPGNU777ORG", +"page_date": "1985-10-04T13:05:00Z", +"age": "0m 0y 0d", +"page_type": "medical", +"medical_context":"birth", +"health_condition_text":"Single spontaneous delivery", +"relevance":"important", +"health_condition_code":"O80", +"summary":"Birth", +"info":"Ana was born in Italy in 1985", +"node":"Milano General Hospital", +"active": true +}, +{ +"id": "919c352f-7e4f-5341-7c22-8423acf76b32", +"book": "ESPGNU777ORG", +"page_date": "1985-10-06T10:00:00Z", +"age": "0y 0m 5d", +"page_type": "biographical", +"relevance":"informational", +"summary":"Birth Certificate", +"info":"Issued in the city of Milano", +"node":"Milano City Hall", +"active": true +} +] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/thalamus-0.9.5/thalamus/demo/populate.sh new/thalamus-0.9.8/thalamus/demo/populate.sh --- old/thalamus-0.9.5/thalamus/demo/populate.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/thalamus-0.9.8/thalamus/demo/populate.sh 2019-03-08 14:30:29.000000000 +0100 @@ -0,0 +1,3 @@ +#!/bin/bash +echo "Importing ...." +python3 ./import_pg.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/thalamus-0.9.5/thalamus/doc/thalamus.rst new/thalamus-0.9.8/thalamus/doc/thalamus.rst --- old/thalamus-0.9.5/thalamus/doc/thalamus.rst 2018-11-27 00:07:32.000000000 +0100 +++ new/thalamus-0.9.8/thalamus/doc/thalamus.rst 2019-03-08 14:39:36.000000000 +0100 @@ -6,7 +6,7 @@ #. **Message server**: A concentrator and message relay from and to the participating nodes in the GNU Health Federation and the GNU Health - Information System (MongoDB). Some of the participating nodes include + Information System (PgSQL). Some of the participating nodes include the GNU Health HMIS, MyGNUHealth mobile PHR application, laboratories, research institutions and civil offices. @@ -56,6 +56,8 @@ * DomiciliaryUnits (/domiciliary-units) +* PersonalDocs (/personal_docs) + Running Thalamus from a WSGI Container -------------------------------------- In production settings, for performance reasons you should use a HTTP server. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/thalamus-0.9.5/thalamus/etc/thalamus.cfg new/thalamus-0.9.8/thalamus/etc/thalamus.cfg --- old/thalamus-0.9.5/thalamus/etc/thalamus.cfg 2018-11-27 00:07:32.000000000 +0100 +++ new/thalamus-0.9.8/thalamus/etc/thalamus.cfg 2019-03-08 14:30:29.000000000 +0100 @@ -1,5 +1,7 @@ + #DB params -MONGO_URI = "mongodb://gnuhealth:HealthRoot@localhost:27017/federation" +POSTGRESQL_URI = "postgresql://localhost/federation" + # Debugging info DEBUG = False diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/thalamus-0.9.5/thalamus/thalamus.py new/thalamus-0.9.8/thalamus/thalamus.py --- old/thalamus-0.9.5/thalamus/thalamus.py 2018-11-27 00:07:32.000000000 +0100 +++ new/thalamus-0.9.8/thalamus/thalamus.py 2019-03-08 14:38:49.000000000 +0100 @@ -8,8 +8,8 @@ ############################################################################## # # GNU Health: The Free Health and Hospital Information System -# Copyright (C) 2008-2018 Luis Falcon <lfal...@gnusolidario.org> -# Copyright (C) 2011-2018 GNU Solidario <hea...@gnusolidario.org> +# Copyright (C) 2008-2019 Luis Falcon <lfal...@gnusolidario.org> +# Copyright (C) 2011-2019 GNU Solidario <hea...@gnusolidario.org> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -27,7 +27,8 @@ ############################################################################## from flask import Flask, redirect, request, jsonify, render_template, url_for from flask_restful import Resource, Api, abort -from flask_pymongo import PyMongo + +import psycopg2 from flask_wtf import FlaskForm from wtforms import BooleanField, StringField, PasswordField, SubmitField, \ @@ -45,8 +46,6 @@ api = Api(app) -mongo = PyMongo(app) - auth = HTTPBasicAuth() ACL = json.load(open(app.config['ACL'],'r')) @@ -59,14 +58,24 @@ app.logger.handlers = gunicorn_logger.handlers app.logger.setLevel(gunicorn_logger.level) -def check_person(person_id): + +#Open a connection to PG Server +conn = psycopg2.connect(app.config['POSTGRESQL_URI']) + +def check_id(table, resid): """ Checks if the Federation ID exists on the GNU Health HIS Returns the instance or null """ - person = mongo.db.people.find_one({'_id' : person_id}) + cur = conn.cursor() + cur.execute ('SELECT id from %s \ + where id = %s limit(1)', (table, resid)) + try: + res, = cur.fetchone() + except: + res = None - return person + return res # Authentication @@ -77,9 +86,16 @@ and checks them against the entry on the people db collection The password is bcrypt hashed """ - user = mongo.db.people.find_one({'_id' : username}) + cur = conn.cursor() + cur.execute ('SELECT data from people \ + where id = %s limit(1)', (username,)) + try: + user, = cur.fetchone() + except: + user = None + if (user): - person = user['_id'] + person = user['id'] hashed_password = user['password'] roles = user['roles'] if bcrypt.checkpw(password.encode('utf-8'), @@ -105,7 +121,7 @@ """ Takes the logged in user roles, method and endpoint as arguments Verifies them against the ACL and returns either True or False - """ + """ for user_role in roles: for acl_entry in ACL: if (acl_entry["role"] == user_role): @@ -132,7 +148,9 @@ """ Retrieves all the people on the person collection """ - people = list(mongo.db.people.find()) + cur = conn.cursor() + cur.execute ('SELECT data from people') + people = cur.fetchall() return jsonify(people) @@ -147,7 +165,14 @@ """ Retrieves the person instance """ - person = mongo.db.people.find_one({'_id' : person_id}) + cur = conn.cursor() + cur.execute ('SELECT data from people \ + where id = %s limit(1)', (person_id,)) + + try: + person, = cur.fetchone() + except: + person = None # Return a 404 if the person ID is not found if not person: @@ -171,13 +196,13 @@ bcrypt_prefixes = ["$2b$", "$2y$"] - if check_person(person_id): + if check_id('people', person_id): abort (422, error="User already exists") if (person_id): if (type(person_id) is str): #Use upper case on the person federation account - values['_id'] = person_id.upper() + values['id'] = person_id.upper() else: abort (422, error="wrong format on person ID") @@ -202,10 +227,13 @@ values['password'] = hashed_pw - # Insert the newly created person in MongoDB - person = mongo.db.people.insert(values) + # Insert the newly created person + cur = conn.cursor() + cur.execute("INSERT INTO people (ID, DATA) VALUES (%(id)s, \ + %(data)s)", {'id': person_id, 'data':json.dumps(values)}) + res = conn.commit() - return jsonify(person) + return res def patch(self, person_id): @@ -216,16 +244,23 @@ #Grab all the data coming from the node client, in JSON format values = json.loads(request.data) - if '_id' in values: + if 'id' in values: # Avoid changing the user ID + print ("Not allowed to change the person ID") abort(422, error="Not allowed to change the person ID") # TO be discussed... # Check if the new ID exist in the Federation, and if it # does not, we may be able to update it. - if check_person(person_id): - update_person = mongo.db.people.update_one({"_id":person_id}, - {"$set": values}) + if check_id('people',person_id): + jdata = json.dumps(values) + # UPDATE the information from the person + # associated to the federation ID + cur = conn.cursor() + cur.execute("UPDATE PEOPLE SET data = data || %s where id = %s", \ + (jdata,person_id)) + conn.commit() + else: abort (404, error="User not found") @@ -235,7 +270,7 @@ used in exceptional cases only, and the instance must be inactive. """ - person = check_person(person_id) + person = check_id('people', person_id) if not person: abort (404, error="User does not exist") @@ -243,7 +278,10 @@ if person['active']: abort (422, error="The user is active.") - delete_person = mongo.db.people.delete_one({"_id":person_id}) + #Delete the person + cur = conn.cursor() + cur.execute("DELETE FROM people WHERE id = %s", (person_id,)) + conn.commit() # Book of Life Resource class Book(Resource): @@ -255,7 +293,12 @@ """ Retrieves the pages of life from the person """ - pages = list(mongo.db.pols.find({'book' : person_id})) + cur = conn.cursor() + cur.execute ('SELECT data from pols where book = %s', (person_id,)) + pages = cur.fetchall() + + return jsonify(pages) + # Return a 404 if the person ID is not found if not pages: @@ -274,9 +317,16 @@ """ Retrieves the page instance """ - page = mongo.db.pols.find_one({'_id': page_id}) + cur = conn.cursor() + cur.execute ('SELECT data from pols \ + where id = %s limit(1)', (page_id,)) + try: + page, = cur.fetchone() + except: + page = None - # Return a 404 if the person ID is not found + + # Return a 404 if the page ID is not found if not page: abort (404, error="Book or page or not found") @@ -290,34 +340,44 @@ values = json.loads(request.data) # Basic validation on page ID exsistance and string type - if (person_id and '_id' in values): - if (type(person_id) is str and type(values['_id'])): - # Insert the newly created PoL in MongoDB - page = mongo.db.pols.insert(values) + if (person_id and 'id' in values): + if (type(person_id) is str and type(values['id'])): + + # Insert the newly created Page of Life from the person Book + cur = conn.cursor() + cur.execute("INSERT INTO pols (ID, BOOK, DATA) \ + VALUES (%(id)s, %(book)s, %(data)s)", \ + {'id': page_id, 'book': person_id, \ + 'data':json.dumps(values)}) + res = conn.commit() + else: print ("wrong format on person or page ID") abort (422, error="wrong format on person or page ID") - return jsonify(page) + return jsonify(res) def patch(self, person_id, page_id): """ Updates the Page of Life """ - #Grab all the data coming from the node client, in JSON format values = json.loads(request.data) - if '_id' in values: - # Avoid changing the user ID + if 'id' in values: + # Avoid changing the page ID abort(422, error="Not allowed to change the page ID") - # TO be discussed... - # Check if the new ID exist in the Federation, and if it - # does not, we may be able to update it. - if check_person(person_id): - update_page = mongo.db.pols.update_one({"_id":page_id}, - {"$set": values}) + if check_id('pols',page_id): + + jdata = json.dumps(values) + # UPDATE the information from the page + # associated to the federation ID book + cur = conn.cursor() + cur.execute("UPDATE pols SET data = data || %s where id = %s", \ + (jdata,page_id)) + conn.commit() + else: abort (404, error="Page not found") @@ -335,17 +395,55 @@ # Personal Documents resource class PersonalDocs(Resource): "Documents associated to the person (scanned info, birth certs, ..)" - def get(self): - documents = list(mongo.db.personal_document.find()) + + decorators = [auth.login_required] # Use the decorator from httpauth + + def get(self, person_id): + """ + Retrieves the documents of a person + """ + cur = conn.cursor() + cur.execute ('SELECT fedacct, pol, data, document from personal_docs \ + where fedacct = %s', (person_id,)) + documents = cur.fetchall() + + return jsonify(documents) + +api.add_resource(PersonalDocs, '/personal_docs/<string:person_id>') + +# Documents associated to a Page of Life +class PolDocs(Resource): + "Documents associated to the person in the context of a Page of Life" + + decorators = [auth.login_required] # Use the decorator from httpauth + + def get(self, person_id, pol_id): + """ + Retrieves the documents of a person + """ + cur = conn.cursor() + cur.execute ('SELECT fedacct, pol, data, document from personal_docs \ + where fedacct = %s', (person_id,pol_id)) + documents = cur.fetchall() + return jsonify(documents) -api.add_resource(PersonalDocs, '/personal-documents') +api.add_resource(PolDocs, '/personal_docs/<string:person_id>/<string:pol_id>') # Domiciliary Units resource class DomiciliaryUnits(Resource): "Domiciliary Units" + + decorators = [auth.login_required] # Use the decorator from httpauth + def get(self): - dus = list(mongo.db.domiciliary_unit.find()) + """ + Retrieves the Domiciliary Units + """ + cur = conn.cursor() + cur.execute ('SELECT data from dus') + dus = cur.fetchall() + return jsonify(dus) api.add_resource(DomiciliaryUnits, '/domiciliary-units') @@ -356,9 +454,14 @@ "Health and other institutions" decorators = [auth.login_required] # Use the decorator from httpauth - def get(self): - institutions = list(mongo.db.institution.find()) + """ + Retrieves the Institutions + """ + cur = conn.cursor() + cur.execute ('SELECT data from institutions') + institutions = cur.fetchall() + return jsonify(institutions) api.add_resource(Institutions, '/institutions') @@ -370,7 +473,7 @@ validators.EqualTo('pconfirm', message='Password mistmatch')]) pconfirm = PasswordField('Confirm Password') update = SubmitField('Update') - + # Update the password of the user with a form @app.route('/password/<person_id>', methods=('GET', 'POST')) @@ -382,10 +485,17 @@ pwd = form.password.data.encode() enc_pwd = bcrypt.hashpw(pwd, bcrypt.gensalt()).decode() values = {'password': enc_pwd} - update_password = \ - mongo.db.people.update_one({"_id":person_id},{"$set": values}) - if update_password: + jdata = json.dumps(values) + # UPDATE the information from the person + # associated to the federation ID + cur = conn.cursor() + cur.execute("UPDATE PEOPLE SET data = data || %s where id = %s", \ + (jdata,person_id)) + update_password = cur.rowcount + conn.commit() + + if update_password > 0: return redirect(url_for('index')) else: error = "Error updating the password" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/thalamus-0.9.5/thalamus.egg-info/PKG-INFO new/thalamus-0.9.8/thalamus.egg-info/PKG-INFO --- old/thalamus-0.9.5/thalamus.egg-info/PKG-INFO 2018-12-16 14:32:13.000000000 +0100 +++ new/thalamus-0.9.8/thalamus.egg-info/PKG-INFO 2019-03-08 17:26:40.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: thalamus -Version: 0.9.5 +Version: 0.9.8 Summary: The GNU Health Federation Message and Authentication Server Home-page: http://health.gnu.org Author: GNU Solidario @@ -15,7 +15,7 @@ #. **Message server**: A concentrator and message relay from and to the participating nodes in the GNU Health Federation and the GNU Health - Information System (MongoDB). Some of the participating nodes include + Information System (PgSQL). Some of the participating nodes include the GNU Health HMIS, MyGNUHealth mobile PHR application, laboratories, research institutions and civil offices. @@ -65,6 +65,8 @@ * DomiciliaryUnits (/domiciliary-units) + * PersonalDocs (/personal_docs) + Running Thalamus from a WSGI Container -------------------------------------- In production settings, for performance reasons you should use a HTTP server. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/thalamus-0.9.5/thalamus.egg-info/SOURCES.txt new/thalamus-0.9.8/thalamus.egg-info/SOURCES.txt --- old/thalamus-0.9.5/thalamus.egg-info/SOURCES.txt 2018-12-16 14:32:13.000000000 +0100 +++ new/thalamus-0.9.8/thalamus.egg-info/SOURCES.txt 2019-03-08 17:26:41.000000000 +0100 @@ -13,6 +13,13 @@ thalamus.egg-info/not-zip-safe thalamus.egg-info/requires.txt thalamus.egg-info/top_level.txt +thalamus/demo/ana_newborn.jpg +thalamus/demo/federation_schema.sql +thalamus/demo/import_pg.py +thalamus/demo/people.json +thalamus/demo/personal_docs.json +thalamus/demo/pols.json +thalamus/demo/populate.sh thalamus/doc/thalamus.rst thalamus/etc/gunicorn.cfg thalamus/etc/roles.cfg diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/thalamus-0.9.5/thalamus.egg-info/requires.txt new/thalamus-0.9.8/thalamus.egg-info/requires.txt --- old/thalamus-0.9.5/thalamus.egg-info/requires.txt 2018-12-16 14:32:13.000000000 +0100 +++ new/thalamus-0.9.8/thalamus.egg-info/requires.txt 2019-03-08 17:26:40.000000000 +0100 @@ -1,6 +1,6 @@ flask flask_httpauth flask_restful -flask_pymongo flask_wtf +psycopg2 bcrypt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/thalamus-0.9.5/version new/thalamus-0.9.8/version --- old/thalamus-0.9.5/version 2018-12-16 12:43:15.000000000 +0100 +++ new/thalamus-0.9.8/version 2019-03-08 17:13:04.000000000 +0100 @@ -1 +1 @@ -0.9.5 +0.9.8