From 7f7abb85f0abf1e098ae737199539bd064c86a1a Mon Sep 17 00:00:00 2001 From: Julien_P Date: Thu, 21 Feb 2019 20:48:03 +0100 Subject: [PATCH] mega cleaning --- GUIDELINES_DEV.md | 37 ++ README.md | 34 +- auth_api/_choices/__init__.py | 2 +- auth_api/_choices/_choices_docs.py | 29 +- auth_api/_choices/_choices_mapping.py | 21 - auth_api/_core/queries_db/__init__.py | 79 +-- auth_api/_core/queries_db/query_delete.py | 28 +- auth_api/_core/queries_db/query_doc.py | 6 +- auth_api/_core/queries_db/query_insert_doc.py | 4 +- auth_api/_core/queries_db/query_list.py | 44 +- auth_api/_core/queries_db/query_solidify.py | 285 ---------- auth_api/_core/queries_db/query_update.py | 317 ++++++----- auth_api/_models/models_generic.py | 159 +----- auth_api/_models/models_user.py | 50 +- auth_api/_parsers/__init__.py | 4 - auth_api/_parsers/parser_classes.py | 62 +- auth_api/_parsers/parser_files.py | 40 -- auth_api/_parsers/parser_pagination.py | 36 -- auth_api/_parsers/parser_queries.py | 51 -- auth_api/_serializers/schema_generic.py | 532 ++---------------- auth_api/_serializers/schema_logs.py | 34 -- auth_api/_serializers/schema_pagination.py | 6 +- auth_api/_serializers/schema_users.py | 67 +-- auth_api/api/__init__.py | 20 +- auth_api/api/api_auth/endpoint_user_login.py | 102 +--- auth_api/api/api_auth/endpoint_user_tokens.py | 8 +- .../api/api_users/endpoint_usr_register.py | 13 +- auth_api/config.py | 8 +- auth_api/config_prod_example.py | 27 +- .../{solidata_prod_git.md => prod_git.md} | 0 .../{solidata_prod_mongo.md => prod_mongo.md} | 0 .../{solidata_prod_nginx.md => prod_nginx.md} | 0 ..._back_supervisor.md => prod_supervisor.md} | 0 ...solidata_prod_ubuntu.md => prod_ubuntu.md} | 0 screenshots/endpoints_dataset_inputs.png | Bin 66358 -> 0 bytes screenshots/endpoints_projects.png | Bin 169981 -> 0 bytes wsgi.py | 4 +- wsgi_preprod.py | 4 +- 38 files changed, 427 insertions(+), 1686 deletions(-) create mode 100644 GUIDELINES_DEV.md delete mode 100644 auth_api/_choices/_choices_mapping.py delete mode 100644 auth_api/_core/queries_db/query_solidify.py delete mode 100644 auth_api/_parsers/parser_files.py delete mode 100644 auth_api/_parsers/parser_pagination.py delete mode 100644 auth_api/_parsers/parser_queries.py rename prod_snippets/{solidata_prod_git.md => prod_git.md} (100%) rename prod_snippets/{solidata_prod_mongo.md => prod_mongo.md} (100%) rename prod_snippets/{solidata_prod_nginx.md => prod_nginx.md} (100%) rename prod_snippets/{solidata_back_supervisor.md => prod_supervisor.md} (100%) rename prod_snippets/{solidata_prod_ubuntu.md => prod_ubuntu.md} (100%) delete mode 100644 screenshots/endpoints_dataset_inputs.png delete mode 100644 screenshots/endpoints_projects.png diff --git a/GUIDELINES_DEV.md b/GUIDELINES_DEV.md new file mode 100644 index 0000000..58fb927 --- /dev/null +++ b/GUIDELINES_DEV.md @@ -0,0 +1,37 @@ +# GUIDELINES FOR DEVELOPMENT + +This project is prone to be developped by several developpers, so we agreed on some basic rules... + +## GENERAL + +- check out our "project" board to have an idea about the priorities we collectively decided to work on +- "see something, say something" : open new issues when you see problems to solve +- document your own issues with everything you have : images, references, snippets, etc... +- we update the `README.md` and the `GUIDELINES_DEV.md` directly on github +- for the markdown files try to [follow those advices](http://www.cirosantilli.com/markdown-style-guide/#dollar-signs-in-shell-code) + +## PYTHON + +- comment your code +- + +## SWAGGER + +- ... + + +## GIT MANAGEMENT + +We are following this git principles : [link to blog](https://guillim.github.io/git/2018/04/24/Git-workflow.html). In brief : +- there are 2 main branches : `master` and `develop` +- new features must be code reviewed and then (if accepted) pulled into the branch `develop` +- once every new feature is accepted and merged into `develop`, `develop` must be merged into `master` to constitute a new release + +please follow those rules when developping new features : +- locally : create a new branch to work on your own feature(s) +- push your branch to the remote repo (github repo) : +> + git push origin +- ask for a pull request on Github from `your_branch` to `develop` +- someone else must be assigned as a code reviewer, whose in charge to accept your code changes and merge +- once accepted / reviewed delete `your_branch` from repo to keep the branches clean diff --git a/README.md b/README.md index 10dcf0b..0b00dde 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,25 @@ -

AUTH SERVICE

+
+

OPEN AUTH MICROSERVICE

+

aka "TOKTOK"

+
------- ## PRESENTATION -#### An REST API for an authentication microservice +#### An REST API for an open source user manager and authentication microservice - this auth server was extracted / insulated / adapted from solidata_backend +- compatible with TADATA! sofware suite ([ApiViz](https://github.com/entrepreneur-interet-general/CIS-front) / [Solidata_frontend](https://github.com/entrepreneur-interet-general/solidata_frontend) / [OpenScraper](https://github.com/entrepreneur-interet-general/OpenScraper) ) -compatible with TADATA! sofware suite ([ApiViz](https://github.com/entrepreneur-interet-general/CIS-front) / [Solidata_frontend](https://github.com/entrepreneur-interet-general/solidata_frontend) / [OpenScraper](https://github.com/entrepreneur-interet-general/OpenScraper) ) +-------- + +## DEVELOPPERS + +- Please check out our **[guidelines](./GUIDELINES_DEV.md)** first +- Check also the **[`prod_snippets`](./prod_snippets)** if you encounter problems while installing locally or setting your server : [install mongodb](./prod_snippets/prod_mongodb.md), [set up supervisor](./prod_snippets/prod_supervisor.md), [set up git](./prod_snippets/prod_git.md), [set up nginx](./prod_snippets/prod_nginx.md), [set up ubuntu](./prod_snippets/prod_ubuntu.md)... ------- @@ -25,11 +34,12 @@ compatible with TADATA! sofware suite ([ApiViz](https://github.com/entrepreneur- ## TECHNICAL POINTS #### Tech stack -- _Language_ : **[Python 3.6](https://www.python.org/)**... yes ... I know ... Python again ... hmmm ... gnnn ... don't judge me ?! +- _Language_ : **[Python 3.6](https://www.python.org/)**... praise be... - _Framework_ : **[Flask](http://flask.pocoo.org/)**... minimalistic Python framework -- _API_ : **[Flask-RestPlus](http://flask-restplus.readthedocs.io/en/stable/)**... Swagger documentation integrated +- _API_ : **[Flask-RestPlus](http://flask-restplus.readthedocs.io/en/stable/)**... Swagger documentation integrated, praise be noirbizarre... - _Security_ : **[Flask-JWT-extended](https://flask-jwt-extended.readthedocs.io/en/latest/)**... wrapper JWT for Flask - _Emailing_ : **[Flask-email](https://pythonhosted.org/Flask-Mail/)**... templating, sending, etc... +- and more... #### Features : @@ -84,7 +94,7 @@ compatible with TADATA! sofware suite ([ApiViz](https://github.com/entrepreneur- - run the app in `default` mode (without possibility to send email) : ```bash - $ python appserver.py + python appserver.py ``` - test the following urls @@ -114,24 +124,24 @@ In practice : - you can run the app in dev mode (with possibility to send email) : ```bash - $ python appserver.py --mode=dev_email + python appserver.py --mode=dev_email ``` - you can choose to deactivate the integrated RSA decryption in the `login` and `register` endpoints ```bash - $ python appserver.py --salt=no + python appserver.py --salt=no ``` - you can choose to deactivate the check for a anonymous JWT in the `login` and `register` endpoints ```bash - $ python appserver.py --anojwt=no + python appserver.py --anojwt=no ``` - you can add up those options in the command line ```bash - $ python appserver.py --anojwt=no --salt=yes --mode=dev_email + python appserver.py --anojwt=no --salt=yes --mode=dev_email ``` ### _PRODUCTION_ @@ -179,8 +189,8 @@ In practice : - run the app in production mode (with possibility to send email) : - ```bash - $ python appserver.py --mode=production + ```bash + python appserver.py --mode=production ``` ------ diff --git a/auth_api/_choices/__init__.py b/auth_api/_choices/__init__.py index bbb7af3..6475571 100644 --- a/auth_api/_choices/__init__.py +++ b/auth_api/_choices/__init__.py @@ -5,5 +5,5 @@ from ._choices_user import * from ._choices_docs import * from ._choices_updates import * -from ._choices_mapping import * +# from ._choices_mapping import * from ._choices_f_types import * \ No newline at end of file diff --git a/auth_api/_choices/_choices_docs.py b/auth_api/_choices/_choices_docs.py index 91a9ec0..f758bb9 100644 --- a/auth_api/_choices/_choices_docs.py +++ b/auth_api/_choices/_choices_docs.py @@ -15,19 +15,30 @@ doc_src_type_list = ["api","xls","xlsx","xml","csv"] -doc_type_list = ["usr","prj","dmt","dmf","dsi","dsr","rec","dso","tag","lic"] +doc_type_list = [ + "usr", + # "prj", + # "dmt", + # "dmf", + # "dsi", + # "dsr", + # "rec", + # "dso", + # "tag", + "lic" +] doc_type_dict = { "usr" : "user", - "prj" : "project", - "dmt" : "datamodel_template", - "dmf" : "datamodel_field", - "dsi" : "dataset_input", - "dsr" : "dataset_raw", - "rec" : "recipe", - "dso" : "dataset_output", - "tag" : "tag", + # "prj" : "project", + # "dmt" : "datamodel_template", + # "dmf" : "datamodel_field", + # "dsi" : "dataset_input", + # "dsr" : "dataset_raw", + # "rec" : "recipe", + # "dso" : "dataset_output", + # "tag" : "tag", "lic" : "licence", } \ No newline at end of file diff --git a/auth_api/_choices/_choices_mapping.py b/auth_api/_choices/_choices_mapping.py deleted file mode 100644 index eb7bb19..0000000 --- a/auth_api/_choices/_choices_mapping.py +++ /dev/null @@ -1,21 +0,0 @@ - -# -*- encoding: utf-8 -*- - -""" -_choices_mapping.py -- all choices related to document's mapping -""" -# from copy import copy, deepcopy - -from log_config import log, pformat - -log.debug("... loading _choices_mapping.py ...") - -### cf: http://flask.pocoo.org/docs/1.0/patterns/fileuploads/ - -mapping_fields = [ - "dmf_to_open_level", - "dsi_to_dmf", - "dmf_to_rec", - "rec_to_func" -] \ No newline at end of file diff --git a/auth_api/_core/queries_db/__init__.py b/auth_api/_core/queries_db/__init__.py index 1261025..531c277 100644 --- a/auth_api/_core/queries_db/__init__.py +++ b/auth_api/_core/queries_db/__init__.py @@ -21,21 +21,8 @@ ### declaring collections as app variables -# mongo_tags = mongo.db[ app.config["MONGO_COLL_TAGS"] ] -mongo_users = mongo.db[ app.config["MONGO_COLL_USERS"] ] -# mongo_projects = mongo.db[ app.config["MONGO_COLL_PROJECTS"] ] -# mongo_datamodels_templates = mongo.db[ app.config["MONGO_COLL_DATAMODELS_TEMPLATES"] ] -# mongo_datamodels_fields = mongo.db[ app.config["MONGO_COLL_DATAMODELS_FIELDS"] ] -# mongo_connectors = mongo.db[ app.config["MONGO_COLL_CONNECTORS"] ] -# mongo_datasets_inputs = mongo.db[ app.config["MONGO_COLL_DATASETS_INPUTS"] ] -# mongo_datasets_raws = mongo.db[ app.config["MONGO_COLL_DATASETS_RAWS"] ] -# mongo_recipes = mongo.db[ app.config["MONGO_COLL_RECIPES"] ] -# mongo_corr_dicts = mongo.db[ app.config["MONGO_COLL_CORR_DICTS"] ] -# mongo_datasets_outputs = mongo.db[ app.config["MONGO_COLL_DATASETS_OUTPUTS"] ] -# mongo_datasets_outputs_doc = mongo.db[ app.config["MONGO_COLL_DATASETS_OUTPUTS_DOC"] ] - -# mongo_licences = mongo.db[ app.config["MONGO_COLL_LICENCES"] ] -mongo_jwt_blacklist = mongo.db[ app.config["MONGO_COLL_JWT_BLACKLIST"] ] +mongo_users = mongo.db[ app.config["MONGO_COLL_USERS"] ] +mongo_jwt_blacklist = mongo.db[ app.config["MONGO_COLL_JWT_BLACKLIST"] ] log.debug(">>> _core.queries_db.__init__.py / INDEXING COLLECTIONS ... " ) @@ -43,17 +30,7 @@ ### drop previous text indexes (only one text index per collection) main_text_fields_to_drop = '$**_text' try : - # mongo_tags.drop_index(main_text_fields_to_drop) mongo_users.drop_index(main_text_fields_to_drop) - # mongo_projects.drop_index(main_text_fields_to_drop) - # mongo_datamodels_templates.drop_index(main_text_fields_to_drop) - # mongo_datamodels_fields.drop_index(main_text_fields_to_drop) - # mongo_datasets_inputs.drop_index(main_text_fields_to_drop) - # mongo_datasets_raws.drop_index(main_text_fields_to_drop) - # mongo_recipes.drop_index(main_text_fields_to_drop) - # mongo_datasets_outputs.drop_index(main_text_fields_to_drop) - # mongo_datasets_outputs_doc.drop_index(main_text_fields_to_drop) - # mongo_licences.drop_index(main_text_fields_to_drop) mongo_jwt_blacklist.drop_index(main_text_fields_to_drop) except: pass @@ -78,57 +55,19 @@ ("data_raw.f_code" ,"text") , ] -# log.debug(">>> _core.queries_db.__init__.py / INDEXING COLLECTIONS : all fields... " ) -# mongo_datasets_inputs.create_index( all_text_fields_to_index, name=all_text_fields_index_name) ### index all fields -# mongo_datasets_raws.create_index( all_text_fields_to_index, name=all_text_fields_index_name) ### index all fields -# mongo_datasets_outputs.create_index( all_text_fields_to_index, name=all_text_fields_index_name) ### index all fields -# mongo_datasets_outputs_doc.create_index( all_text_fields_to_index, name=all_text_fields_index_name) ### index all fields log.debug(">>> _core.queries_db.__init__.py / INDEXING COLLECTIONS : main fields... " ) -mongo_users.create_index( main_text_fields_to_index, name=main_text_fields_index_name) -# mongo_tags.create_index( main_text_fields_to_index, name=main_text_fields_index_name) -# mongo_projects.create_index( main_text_fields_to_index, name=main_text_fields_index_name) -# mongo_datamodels_templates.create_index( main_text_fields_to_index, name=main_text_fields_index_name) -# mongo_datamodels_fields.create_index( main_text_fields_to_index, name=main_text_fields_index_name) -# mongo_recipes.create_index( main_text_fields_to_index, name=main_text_fields_index_name) - -# mongo_licences.create_index( main_text_fields_to_index, name=main_text_fields_index_name) -mongo_jwt_blacklist.create_index( main_text_fields_to_index, name=main_text_fields_index_name) +mongo_users.create_index( main_text_fields_to_index, name=main_text_fields_index_name) +mongo_jwt_blacklist.create_index( main_text_fields_to_index, name=main_text_fields_index_name) db_dict = { - # "mongo_tags" : mongo_tags, - "mongo_users" : mongo_users, - # "mongo_projects" : mongo_projects, - # "mongo_datamodels_templates" : mongo_datamodels_templates, - # "mongo_datamodels_fields" : mongo_datamodels_fields, - # "mongo_connectors" : mongo_connectors, - # "mongo_datasets_inputs" : mongo_datasets_inputs, - # "mongo_datasets_raws" : mongo_datasets_raws, - # "mongo_recipes" : mongo_recipes, - # "mongo_corr_dicts" : mongo_corr_dicts, - - # "mongo_datasets_outputs" : mongo_datasets_outputs, - # "mongo_datasets_outputs_doc" : mongo_datasets_outputs_doc, - - # "mongo_licences" : mongo_licences, - "mongo_jwt_blacklist" : mongo_jwt_blacklist, + "mongo_users" : mongo_users, + "mongo_jwt_blacklist" : mongo_jwt_blacklist, } db_dict_by_type = { - # "tag" : mongo_tags, - "usr" : mongo_users, - # "prj" : mongo_projects, - # "dmt" : mongo_datamodels_templates, - # "dmf" : mongo_datamodels_fields, - # "dsi" : mongo_datasets_inputs, - # "dsr" : mongo_datasets_raws, - # "rec" : mongo_recipes, - - # "dso" : mongo_datasets_outputs, - # "dso_doc" : mongo_datasets_outputs_doc, - - # "lic" : mongo_licences, - "jwt_blacklist" : mongo_jwt_blacklist, + "usr" : mongo_users, + "jwt_blacklist" : mongo_jwt_blacklist, } def select_collection(coll_name): @@ -195,8 +134,8 @@ def get_results(): from .query_list import * from .query_delete import * from .query_update import * -# from .query_solidify import * from .query_insert_doc import * +# from .query_solidify import * # from .query_build_dso import * print() diff --git a/auth_api/_core/queries_db/query_delete.py b/auth_api/_core/queries_db/query_delete.py index 19e62d9..1d9f45c 100644 --- a/auth_api/_core/queries_db/query_delete.py +++ b/auth_api/_core/queries_db/query_delete.py @@ -33,19 +33,19 @@ def Query_db_delete ( # marshaller = Marshaller(ns, models) ### default values - db_collection = db_dict_by_type[document_type] - document_type_full = doc_type_dict[document_type] - user_id = user_oid = None - user_role = "anonymous" - doc_oid = ObjectId(doc_id) - document_out = None - response_code = 401 + db_collection = db_dict_by_type[document_type] + document_type_full = doc_type_dict[document_type] + user_id = user_oid = None + user_role = "anonymous" + doc_oid = ObjectId(doc_id) + document_out = None + response_code = 401 user_allowed_to_delete = False - message = "dear user, you don't have the credentials to delete this {} with this oid : {}".format(document_type_full, doc_id) + message = "dear user, you don't have the credentials to delete this {} with this oid : {}".format(document_type_full, doc_id) if claims or claims!={} : user_role = claims["auth"]["role"] - user_id = claims["_id"] ### get the oid as str + user_id = claims["_id"] ### get the oid as str if user_role != "anonymous" : user_oid = ObjectId(user_id) log.debug("user_oid : %s", user_oid ) @@ -56,14 +56,14 @@ def Query_db_delete ( # log.debug( "document : \n%s", pformat(document) ) else : response_code = 400 - document = None + document = None ### sum up all query arguments query_resume = { - "document_type" : document_type, - "doc_id" : doc_id, - "user_id" : user_id, - "user_role" : user_role, + "document_type" : document_type, + "doc_id" : doc_id, + "user_id" : user_id, + "user_role" : user_role, "is_member_of_team" : False } diff --git a/auth_api/_core/queries_db/query_doc.py b/auth_api/_core/queries_db/query_doc.py index 8e87d02..45f4889 100644 --- a/auth_api/_core/queries_db/query_doc.py +++ b/auth_api/_core/queries_db/query_doc.py @@ -8,7 +8,7 @@ import random import pandas as pd -import numpy as np +import numpy as np from pandas.io.json import json_normalize from log_config import log, pformat @@ -93,11 +93,11 @@ def get_dso_docs(doc_oid, query_args) : dso_doc_collection = db_dict_by_type['dso_doc'] - query = build_first_term_query(doc_oid, query_args) + query = build_first_term_query(doc_oid, query_args) log.debug('query : \n%s', pformat(query) ) # results = dso_doc_collection.find({'oid_dso' : doc_oid }) - cursor = dso_doc_collection.find(query) + cursor = dso_doc_collection.find(query) results = list(cursor) diff --git a/auth_api/_core/queries_db/query_insert_doc.py b/auth_api/_core/queries_db/query_insert_doc.py index 6aedc89..962b6e9 100644 --- a/auth_api/_core/queries_db/query_insert_doc.py +++ b/auth_api/_core/queries_db/query_insert_doc.py @@ -41,10 +41,10 @@ def Query_db_insert ( log.debug("... _core.queries_db.query_insert_doc.py ... %s", document_type ) ### default values - db_collection = db_dict_by_type[document_type] + db_collection = db_dict_by_type[document_type] document_type_full = doc_type_dict[document_type] - filter_doc = { field_to_check : value_to_check } + filter_doc = { field_to_check : value_to_check } log.debug('filter_doc : %s', pformat(filter_doc) ) ### check if doc already exists diff --git a/auth_api/_core/queries_db/query_list.py b/auth_api/_core/queries_db/query_list.py index 68590fb..12ad8be 100644 --- a/auth_api/_core/queries_db/query_list.py +++ b/auth_api/_core/queries_db/query_list.py @@ -5,8 +5,8 @@ """ import re -import pandas as pd -from pandas.io.json import json_normalize +import pandas as pd +from pandas.io.json import json_normalize from log_config import log, pformat log.debug("... _core.queries_db.query_list.py ..." ) @@ -33,29 +33,29 @@ def Query_db_list ( page_args, query_args, roles_for_complete = ["admin"], - check_teams = True + check_teams = True ): ### prepare marshaller marshaller = Marshaller(ns, models) ### default values - db_collection = db_dict_by_type[document_type] - document_type_full = doc_type_dict[document_type] - user_id = user_oid = None - user_role = "anonymous" - documents_out_in_team = None + db_collection = db_dict_by_type[document_type] + document_type_full = doc_type_dict[document_type] + user_id = user_oid = None + user_role = "anonymous" + documents_out_in_team = None documents_out_not_team = None - message = None - dft_open_level_show = ["open_data"] - response_code = 200 - cursor_in_team_count = 0 - cursor_not_team_count = 0 + message = None + dft_open_level_show = ["open_data"] + response_code = 200 + cursor_in_team_count = 0 + cursor_not_team_count = 0 ### get user's role and _id # user_id = get_jwt_identity() ### get the oid as str if claims or claims != {} : - user_role = claims["auth"]["role"] + user_role = claims["auth"]["role"] user_id = claims["_id"] ### get the oid as str if user_role != "anonymous" : user_oid = ObjectId(user_id) @@ -87,20 +87,17 @@ def Query_db_list ( ### get query arguments log.debug('query_args : \n%s', pformat(query_args) ) - # q_title = query_args.get('q_title', None ) - # q_description = query_args.get('q_description', None ) q_search_for = query_args.get('search_for', None ) q_oid_list = query_args.get('oids', None ) - # q_oid_tags = query_args.get('tags', None ) q_only_stats = query_args.get('only_stats', False ) q_ignore_team = query_args.get('ignore_teams', False ) - q_pivot = query_args.get('pivot_results', False ) + q_pivot = query_args.get('pivot_results', False ) q_normalize = query_args.get('normalize', False ) ### pipelines for basic query pipeline_queries = {} - pipe_concat = [] + pipe_concat = [] do_query_pipe = False @@ -128,15 +125,6 @@ def Query_db_list ( pipe_concat.append(pipe_oids) log.debug('pipe_concat + oid_list : %s', pipe_concat) - # if q_title != None : - # do_query_pipe = True - # pipe_title = { "infos.title" : q_title } - # pipe_concat.append(pipe_title) - - # if q_description != None : - # do_query_pipe = True - # pipe_description = { "infos.description" : q_description } - # pipe_concat.append(pipe_description) ### search by string in indexed fields if q_search_for != None : diff --git a/auth_api/_core/queries_db/query_solidify.py b/auth_api/_core/queries_db/query_solidify.py deleted file mode 100644 index 01967b3..0000000 --- a/auth_api/_core/queries_db/query_solidify.py +++ /dev/null @@ -1,285 +0,0 @@ -# -*- encoding: utf-8 -*- - -""" -_core/queries_db/query_solidify.py -""" - -from log_config import log, pformat -log.debug("... _core.queries_db.query_solidify.py ..." ) - -from datetime import datetime, timedelta -from bson.objectid import ObjectId -from flask_restplus import marshal - -from . import db_dict_by_type, Marshaller -from auth_api._choices._choices_docs import doc_type_dict -from auth_api._core.solidify import * - - -import sys - -def str_to_class(classname): - return getattr(sys.modules[__name__], classname) - - -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -### GLOBAL FUNCTION TO ENRICH ONE DOC FROM DB -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -### cf : response codes : https://restfulapi.net/http-status-codes/ - -def Query_db_solidify ( - ns, - models, - document_type, - doc_id, - claims, - roles_for_complete = ["admin"], - payload = {} - ): - - print() - print("-+- "*40) - log.debug("... _core.queries_db.Query_db_solidify.py ..." ) - - ### get mongodb collections - prj_collection = db_dict_by_type['prj'] - dmt_collection = db_dict_by_type['dmt'] - dmf_collection = db_dict_by_type['dmf'] - dsi_collection = db_dict_by_type['dsi'] - rec_collection = db_dict_by_type['rec'] - - - ### prepare marshaller - # marshaller = Marshaller(ns, models) - - ### default values - db_collection = db_dict_by_type[document_type] - document_type_full = doc_type_dict[document_type] - user_id = user_oid = None - user_role = "anonymous" - document_out = None - message = None - dft_open_level_show = ["open_data"] - response_code = 200 - - if claims or claims!={} : - user_role = claims["auth"]["role"] - user_id = claims["_id"] ### get the oid as str - if user_role != "anonymous" : - user_oid = ObjectId(user_id) - log.debug("user_oid : %s", user_oid ) - dft_open_level_show += ["commons"] - - ### retrieve doc (PRJ f.e.) from db - if ObjectId.is_valid(doc_id) : - doc_oid = ObjectId(doc_id) - document = db_collection.find_one( {"_id": doc_oid } ) - # log.debug( "document : \n%s", pformat(document) ) - else : - response_code = 400 - document = None - - ### sum up all query arguments - query_resume = { - "document_type" : document_type, - "doc_id" : doc_id, - "user_id" : user_id, - "user_role" : user_role, - "is_member_of_team" : False, - "payload" : payload - } - - if document : - - ### check doc's specs : public_auth, team... - doc_open_level_edit = document["public_auth"]["open_level_edit"] - log.debug( "doc_open_level_edit : %s", doc_open_level_edit ) - - ### get doc's team infos - if "team" in document : - team_oids = [ t["oid_usr"] for t in document["team"] ] - log.debug( "team_oids : \n%s", pformat(team_oids) ) - - - ### marshal out results given user's claims / doc's public_auth / doc's team ... - - # for admin or members of the team --> complete infos model - if user_role in roles_for_complete or user_oid in team_oids : - - log.debug( "payload : \n%s", pformat(payload) ) - payload_data = payload[0] - - ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### - ### OPERATIONS RELATED TO DOCUMENTS - ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### - - ### store db docs in a dict - documents = { - "src_doc" : document - } - - ### check if recipe run implies to modify DMT, DSI, PRJ's MAPPING... - # is_complex_rec = payload_data.get( "is_complex_rec", False ) - - ### check if the doc requested is already running - is_doc_running = document["log"].get("is_running", False) - log.debug( "is_doc_running : %s", is_doc_running ) - - - ### load corresponding DMT, DSI, PRJ if is_complex_rec - if document_type in ["prj"] : - - ### get datasets from document - datasets = document["datasets"] - dmt_refs = datasets["dmt_list"] - dsi_refs = datasets["dsi_list"] - - ### load DMT from db - dmt_doc = dmt_collection.find_one( {"_id" : dmt_refs[0]["oid_dmt"] } ) - documents["dmt_doc"] = dmt_doc - log.debug( "dmt_doc loaded ... " ) - - ### load DMFs from db - dmt_dmf_refs = dmt_doc["datasets"]["dmf_list"] - dmf_oids = [ dmf_ref["oid_dmf"] for dmf_ref in dmt_dmf_refs ] - dmf_list_cursor = dmf_collection.find({"_id" : {"$in" : dmf_oids} }) - dmf_list = list(dmf_list_cursor) - documents["dmf_list"] = dmf_list - log.debug( "dmf_list loaded ... " ) - - ### load DSIs from db - dsi_oids = [ dsi_ref["oid_dsi"] for dsi_ref in dsi_refs ] - dsi_list_cursor = dsi_collection.find({"_id" : {"$in" : dsi_oids} }) - dsi_list = list(dsi_list_cursor) - documents["dsi_list"] = dsi_list - log.debug( "dsi_list loaded ... " ) - - ### check if related dsi are already running - is_running_dsi = [ dsi["log"].get("is_running", False) for dsi in dsi_list ] - is_running_dsi_set = set(is_running_dsi) - log.debug( "is_running_dsi_set : %s", is_running_dsi_set ) - - are_dsi_running = True - if len(is_running_dsi_set) == 1 : - if list(is_running_dsi_set)[0] == False : - are_dsi_running = False - log.debug( "are_dsi_running : %s", are_dsi_running ) - - if are_dsi_running == False and is_doc_running == True : - document_ = prj_collection.update_one( {"_id" : doc_oid }, { "$set" : { "log.is_running" : False } } ) - document = prj_collection.find_one( {"_id" : doc_oid } ) - documents["src_doc"] = document - - - ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### - ### OPERATIONS RELATED TO RECIPE - ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### - - ### get recipe id to run from payload - recipe_to_run = payload_data["id_rec"] - log.debug( "recipe_to_run : %s", recipe_to_run ) - - rec_oid = ObjectId(recipe_to_run) - log.debug( "rec_oid : %s", rec_oid ) - - ### retrieve recipe params from doc's mapping - map_rec_list = document["mapping"]["map_rec"] - # log.debug( "map_rec_list : \n%s", pformat(map_rec_list) ) - rec_params = next( item for item in map_rec_list if item["oid_rec"] == rec_oid ) - rec_params_ = rec_params["rec_params"] - log.debug( "rec_params_ : \n%s", pformat(rec_params_) ) - - need_add_dmf = rec_params_.get('new_dmfs_list', False) - if need_add_dmf : - new_dmf_oids = [ ObjectId(dmf_ref["oid_dmf"]) for dmf_ref in need_add_dmf ] - new_dmf_list_cursor = dmf_collection.find({"_id" : {"$in" : new_dmf_oids} }) - new_dmf_list = list(new_dmf_list_cursor) - rec_params_["new_dmfs_list"] = new_dmf_list - - ### retrieve recipe from db - recipe_doc = rec_collection.find_one( { "_id" : rec_oid }) - log.debug( "recipe_doc : \n%s", pformat(recipe_doc) ) - documents["rec_doc"] = recipe_doc - - ### choose the function to run from recipe_doc in db - recipe_map = recipe_doc["mapping"]["map_func"][0] - - recipe_func_class = recipe_map["function_class"] - log.debug( "recipe_func_class : %s", recipe_func_class ) - - recipe_func_runner = recipe_map["function_runner"] - log.debug( "recipe_func_runner : %s", recipe_func_runner ) - - - - - ### load the function & pass the parameters - - # Get class from globals and create an instance - # log.debug( "globals() : \n%s", pformat(globals()) ) - ### WARNING !!! --> multithreading could make OS crash - ### cf : https://stackoverflow.com/questions/50168647/multiprocessing-causes-python-to-crash-and-gives-an-error-may-have-been-in-progr - ### add in .bask or venv/bin/activate : - # 'export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES' - - - module = globals()[recipe_func_class]( - user_oid, - src_docs = documents, - rec_params = rec_params_, - use_multiprocessing = False, - ### cf : http://blog.shenwei.me/python-multiprocessing-pool-difference-between-map-apply-map_async-apply_async/ - pool_or_process = "process", ### dft = "pool" | "process" --> "pool" : wait for process to finish | "process" : launch - async_or_starmap = "starmap", ### "async" | "starmap" - cpu_number = 2 - ) - - # Get the function (from the instance) that we need to call to run the function - solidify_func = getattr(module, recipe_func_runner) - - ### run the solidifying function - solidify_func() - - - - ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### - ### OPERATIONS RELATED TO RESPONSE - ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### - - ### send back updated document - document_updated = db_collection.find_one( {"_id": ObjectId(doc_id) } ) - document_out = marshal( document_updated, models["model_doc_out"] ) - - - - ### TO DO : in case doc solidified is DSI --> f_data sliced for preview - ### slice/trim : document_out["data_raw"]["f_data"] - - - # flag as member of doc's team - if user_oid in team_oids : - query_resume["is_member_of_team"] = True - - message = "dear user, there is the complete {} you requested ".format(document_type_full) - - - # for other users - else : - - response_code = 401 - ### unvalid credentials / empty response - message = "dear user, you don't have the credentials to solidify this {} with this oid : {}".format(document_type_full, doc_id) - - - - else : - ### no document / empty response - response_code = 404 - message = "dear user, there is no {} with this oid : {}".format(document_type_full, doc_id) - - ### return the response - return { - "msg" : message , - "data" : document_out, - "query" : query_resume, - }, response_code \ No newline at end of file diff --git a/auth_api/_core/queries_db/query_update.py b/auth_api/_core/queries_db/query_update.py index aee5357..4f9e9fd 100644 --- a/auth_api/_core/queries_db/query_update.py +++ b/auth_api/_core/queries_db/query_update.py @@ -15,77 +15,77 @@ from auth_api._choices._choices_docs import doc_type_dict -def check_if_prj_is_buildable (doc_prj) : - """ - check if prj has enough mapping to be buildable - """ +# def check_if_prj_is_buildable (doc_prj) : +# """ +# check if prj has enough mapping to be buildable +# """ - print("-+- "*40) - log.debug( "... check_if_prj_is_buildable ... " ) +# print("-+- "*40) +# log.debug( "... check_if_prj_is_buildable ... " ) - is_buildable = False +# is_buildable = False - prj_dmt = doc_prj["datasets"]["dmt_list"] - prj_dsi = doc_prj["datasets"]["dsi_list"] - prj_map_open = doc_prj["mapping"]["dmf_to_open_level"] - prj_map_dsi = doc_prj["mapping"]["dsi_to_dmf"] +# prj_dmt = doc_prj["datasets"]["dmt_list"] +# prj_dsi = doc_prj["datasets"]["dsi_list"] +# prj_map_open = doc_prj["mapping"]["dmf_to_open_level"] +# prj_map_dsi = doc_prj["mapping"]["dsi_to_dmf"] - ### check if prj contains dmt and dsi - if len(prj_dmt)>0 and len(prj_dsi)>0 : +# ### check if prj contains dmt and dsi +# if len(prj_dmt)>0 and len(prj_dsi)>0 : - log.debug( "... lengths prj_dmt & prj_map_dsi : OK ... " ) +# log.debug( "... lengths prj_dmt & prj_map_dsi : OK ... " ) - ### check if prj contains dmt and dsi - if len(prj_map_open)>0 and len(prj_map_dsi)>0 : +# ### check if prj contains dmt and dsi +# if len(prj_map_open)>0 and len(prj_map_dsi)>0 : - log.debug( "... lengths prj_map_open & prj_map_dsi : OK ... " ) +# log.debug( "... lengths prj_map_open & prj_map_dsi : OK ... " ) - ### set of unique values of dmf from prj_map_open - prj_dsi_set = { d['oid_dsi'] for d in prj_dsi } - log.debug( "... prj_dsi_set : \n%s : ", pformat(prj_dsi_set) ) +# ### set of unique values of dmf from prj_map_open +# prj_dsi_set = { d['oid_dsi'] for d in prj_dsi } +# log.debug( "... prj_dsi_set : \n%s : ", pformat(prj_dsi_set) ) - ### set of unique values of dmf from prj_map_open - prj_map_dmf_set = { d['oid_dmf'] for d in prj_map_open } - log.debug( "... prj_map_dmf_set : \n%s : ", pformat(prj_map_dmf_set) ) +# ### set of unique values of dmf from prj_map_open +# prj_map_dmf_set = { d['oid_dmf'] for d in prj_map_open } +# log.debug( "... prj_map_dmf_set : \n%s : ", pformat(prj_map_dmf_set) ) - ### unique values of dsi from prj_map_dsi - prj_map_dsi_dict = { d['oid_dsi'] : { "dmf_list" : [] } for d in prj_map_dsi } - for d in prj_map_dsi : - prj_map_dsi_dict[ d['oid_dsi'] ]["dmf_list"].append( d["oid_dmf"] ) - log.debug( "... prj_map_dsi_dict : \n%s : ", pformat(prj_map_dsi_dict) ) +# ### unique values of dsi from prj_map_dsi +# prj_map_dsi_dict = { d['oid_dsi'] : { "dmf_list" : [] } for d in prj_map_dsi } +# for d in prj_map_dsi : +# prj_map_dsi_dict[ d['oid_dsi'] ]["dmf_list"].append( d["oid_dmf"] ) +# log.debug( "... prj_map_dsi_dict : \n%s : ", pformat(prj_map_dsi_dict) ) - ### set of unique values of dmf for each dsi from prj_map_dsi_dict - prj_map_dsi_sets = { k : set(v['dmf_list']) for k,v in prj_map_dsi_dict.items() } - log.debug( "... prj_map_dsi_sets : \n%s : ", pformat(prj_map_dsi_sets) ) +# ### set of unique values of dmf for each dsi from prj_map_dsi_dict +# prj_map_dsi_sets = { k : set(v['dmf_list']) for k,v in prj_map_dsi_dict.items() } +# log.debug( "... prj_map_dsi_sets : \n%s : ", pformat(prj_map_dsi_sets) ) - ### check if dmf in prj_map_dsi are in prj_map_open - dsi_mapped_not_in_prj = 0 - dsi_mapped_but_no_dmf_mapped_in_prj_map = 0 +# ### check if dmf in prj_map_dsi are in prj_map_open +# dsi_mapped_not_in_prj = 0 +# dsi_mapped_but_no_dmf_mapped_in_prj_map = 0 - for dsi_oid, dsi_dmf_mapped_set in prj_map_dsi_sets.items() : +# for dsi_oid, dsi_dmf_mapped_set in prj_map_dsi_sets.items() : - log.debug( "... dsi_oid : %s ", dsi_oid ) +# log.debug( "... dsi_oid : %s ", dsi_oid ) - if dsi_oid in prj_dsi_set : - ### check if dsi_dmf_mapped_set contains at least 1 dmf from prj_map_dmf_set - log.debug( "... dsi_dmf_mapped_set : \n%s ", pformat(dsi_dmf_mapped_set) ) - log.debug( "... prj_map_dmf_set : \n%s ", pformat(prj_map_dmf_set) ) - intersection = dsi_dmf_mapped_set & prj_map_dmf_set - log.debug( "... intersection : %s ", intersection ) - len_intersection = len(intersection) - if len_intersection == 0 : - dsi_mapped_but_no_dmf_mapped_in_prj_map += 1 - - else : - dsi_mapped_not_in_prj += 1 +# if dsi_oid in prj_dsi_set : +# ### check if dsi_dmf_mapped_set contains at least 1 dmf from prj_map_dmf_set +# log.debug( "... dsi_dmf_mapped_set : \n%s ", pformat(dsi_dmf_mapped_set) ) +# log.debug( "... prj_map_dmf_set : \n%s ", pformat(prj_map_dmf_set) ) +# intersection = dsi_dmf_mapped_set & prj_map_dmf_set +# log.debug( "... intersection : %s ", intersection ) +# len_intersection = len(intersection) +# if len_intersection == 0 : +# dsi_mapped_but_no_dmf_mapped_in_prj_map += 1 + +# else : +# dsi_mapped_not_in_prj += 1 - log.debug( "... dsi_mapped_not_in_prj : %s ", dsi_mapped_not_in_prj ) - log.debug( "... dsi_mapped_but_no_dmf_mapped_in_prj_map : %s ", dsi_mapped_but_no_dmf_mapped_in_prj_map ) +# log.debug( "... dsi_mapped_not_in_prj : %s ", dsi_mapped_not_in_prj ) +# log.debug( "... dsi_mapped_but_no_dmf_mapped_in_prj_map : %s ", dsi_mapped_but_no_dmf_mapped_in_prj_map ) - if dsi_mapped_but_no_dmf_mapped_in_prj_map == 0 : - is_buildable = True +# if dsi_mapped_but_no_dmf_mapped_in_prj_map == 0 : +# is_buildable = True - return is_buildable +# return is_buildable @@ -101,7 +101,7 @@ def Query_db_update ( doc_id, claims, roles_for_complete = ["admin"], - payload = {} + payload = {} ): print() @@ -109,20 +109,20 @@ def Query_db_update ( log.debug("... _core.queries_db.query_update.py ... %s", document_type ) ### default values - db_collection = db_dict_by_type[document_type] + db_collection = db_dict_by_type[document_type] document_type_full = doc_type_dict[document_type] user_id = user_oid = None - user_role = "anonymous" - document_out = None - message = None + user_role = "anonymous" + document_out = None + message = None # dft_open_level_show = ["open_data"] - response_code = 200 + response_code = 200 if claims or claims!={} : - user_role = claims["auth"]["role"] - user_id = claims["_id"] ### get the oid as str + user_role = claims["auth"]["role"] + user_id = claims["_id"] ### get the oid as str if user_role != "anonymous" : - user_oid = ObjectId(user_id) + user_oid = ObjectId(user_id) log.debug("user_oid : %s", user_oid ) # dft_open_level_show += ["commons"] @@ -137,12 +137,12 @@ def Query_db_update ( ### sum up all query arguments query_resume = { - "document_type" : document_type, - "doc_id" : doc_id, - "user_id" : user_id, - "user_role" : user_role, + "document_type" : document_type, + "doc_id" : doc_id, + "user_id" : user_id, + "user_role" : user_role, "is_member_of_team" : False, - "payload" : payload + "payload" : payload } @@ -176,87 +176,87 @@ def Query_db_update ( log.debug( "field_to_update : %s", field_to_update ) add_to_list = payload_data.get('add_to_list', False ) - is_mapping = payload_data.get('is_mapping', False ) - - if is_mapping : - - payload_map = {} - delete_from_mapping = payload_data.get('del_mapping', False ) - - # cf : https://stackoverflow.com/questions/10522347/mongodb-update-objects-in-a-documents-array-nested-updating - - if field_to_update == "mapping.dmf_to_open_level" : - selector_f = field_to_update+".oid_dmf" - selector_v = payload_map["oid_dmf"] = ObjectId( payload_data["id_dmf"] ) - selector = { selector_f : selector_v } - payload_map["open_level_show"] = payload_data["open_level_show"] - - elif field_to_update == "mapping.dsi_to_dmf" : - selector_f = field_to_update+".dsi_header" - selector_v = payload_map["dsi_header"] = payload_data["dsi_header"] - selector_f_ = field_to_update+".oid_dsi" - selector_v_ = payload_map["oid_dsi"] = ObjectId ( payload_data["id_dsi"] ) - selector = { selector_f : selector_v, selector_f_ : selector_v_ } - if payload_data["id_dmf"] == "_ignore_" or delete_from_mapping : - # payload_map["oid_dmf"] = None - pass - else : - payload_map["oid_dmf"] = ObjectId( payload_data["id_dmf"] ) - - elif field_to_update == "mapping.map_rec" : - selector_f = field_to_update+".oid_rec" - selector_v = payload_map["oid_rec"] = ObjectId( payload_data["id_rec"] ) - selector = { selector_f : selector_v } - payload_map["rec_params"] = payload_data["rec_params"] - - # elif field_to_update == "mapping.rec_to_func" : - # selector_f = field_to_update+".oid_dmf" - # selector_v = payload_map["oid_rec"] = ObjectId( payload_data["id_rec"] ) - # selector = { selector_f : selector_v } - - log.debug( "selector : \n%s", pformat(selector) ) - log.debug( "payload_map : \n%s", pformat(payload_map) ) - - log.debug( "cursor : \n%s", pformat({ "_id" : ObjectId(doc_id), **selector }) ) - - ### update mapping if selector_v already exists -> update array element - - log.debug( "update mapping / existing mapper... " ) - ### $set from array if delete_mapping flag is False - if not delete_from_mapping : - payload_set = { field_to_update+".$."+key : payload_map[key] for key in payload_map.keys() } - doc_mapped = db_collection.update_one( - { "_id" : doc_oid, **selector }, - { "$set" : - payload_set - # { field_to_update+".$."+key : payload_map[key] for key in payload_map.keys() } - }, - ) - ### $pull from array if delete_mapping flag is True - else : - payload_pull = payload_map - doc_mapped = db_collection.update_one( - { "_id" : doc_oid, **selector }, - { "$pull" : { - field_to_update : payload_pull - } - }, - ) - log.debug( "...doc_mapped : \n%s ", pformat(doc_mapped) ) - log.debug( "...doc_mapped.matched_count : \n%s ", pformat(doc_mapped.matched_count) ) - - # update mapping if selector_v doesn't exist -> add to array - if doc_mapped.matched_count == 0 : - log.debug( "update mapping / non existing mapper... " ) - doc_mapped = db_collection.update_one( - { "_id" : doc_oid }, - { "$addToSet" : - { field_to_update : payload_map } - }, - upsert=True - ) + is_mapping = payload_data.get('is_mapping', False ) + + # if is_mapping : + + # payload_map = {} + # delete_from_mapping = payload_data.get('del_mapping', False ) + + # # cf : https://stackoverflow.com/questions/10522347/mongodb-update-objects-in-a-documents-array-nested-updating + + # if field_to_update == "mapping.dmf_to_open_level" : + # selector_f = field_to_update+".oid_dmf" + # selector_v = payload_map["oid_dmf"] = ObjectId( payload_data["id_dmf"] ) + # selector = { selector_f : selector_v } + # payload_map["open_level_show"] = payload_data["open_level_show"] + + # elif field_to_update == "mapping.dsi_to_dmf" : + # selector_f = field_to_update+".dsi_header" + # selector_v = payload_map["dsi_header"] = payload_data["dsi_header"] + # selector_f_ = field_to_update+".oid_dsi" + # selector_v_ = payload_map["oid_dsi"] = ObjectId ( payload_data["id_dsi"] ) + # selector = { selector_f : selector_v, selector_f_ : selector_v_ } + # if payload_data["id_dmf"] == "_ignore_" or delete_from_mapping : + # # payload_map["oid_dmf"] = None + # pass + # else : + # payload_map["oid_dmf"] = ObjectId( payload_data["id_dmf"] ) + + # elif field_to_update == "mapping.map_rec" : + # selector_f = field_to_update+".oid_rec" + # selector_v = payload_map["oid_rec"] = ObjectId( payload_data["id_rec"] ) + # selector = { selector_f : selector_v } + # payload_map["rec_params"] = payload_data["rec_params"] + + # # elif field_to_update == "mapping.rec_to_func" : + # # selector_f = field_to_update+".oid_dmf" + # # selector_v = payload_map["oid_rec"] = ObjectId( payload_data["id_rec"] ) + # # selector = { selector_f : selector_v } + + # log.debug( "selector : \n%s", pformat(selector) ) + # log.debug( "payload_map : \n%s", pformat(payload_map) ) + + # log.debug( "cursor : \n%s", pformat({ "_id" : ObjectId(doc_id), **selector }) ) + + # ### update mapping if selector_v already exists -> update array element + + # log.debug( "update mapping / existing mapper... " ) + # ### $set from array if delete_mapping flag is False + # if not delete_from_mapping : + # payload_set = { field_to_update+".$."+key : payload_map[key] for key in payload_map.keys() } + # doc_mapped = db_collection.update_one( + # { "_id" : doc_oid, **selector }, + # { "$set" : + # payload_set + # # { field_to_update+".$."+key : payload_map[key] for key in payload_map.keys() } + # }, + # ) + # ### $pull from array if delete_mapping flag is True + # else : + # payload_pull = payload_map + # doc_mapped = db_collection.update_one( + # { "_id" : doc_oid, **selector }, + # { "$pull" : { + # field_to_update : payload_pull + # } + # }, + # ) + # log.debug( "...doc_mapped : \n%s ", pformat(doc_mapped) ) + # log.debug( "...doc_mapped.matched_count : \n%s ", pformat(doc_mapped.matched_count) ) + + # # update mapping if selector_v doesn't exist -> add to array + # if doc_mapped.matched_count == 0 : + # log.debug( "update mapping / non existing mapper... " ) + # doc_mapped = db_collection.update_one( + # { "_id" : doc_oid }, + # { "$addToSet" : + # { field_to_update : payload_map } + # }, + # upsert=True + # ) - elif add_to_list : + if add_to_list : log.debug( "add_to_list... " ) @@ -404,19 +404,19 @@ def Query_db_update ( query_resume["is_member_of_team"] = True ### update log if document is a prj - if document_type == "prj" : + # if document_type == "prj" : - ### get updated doc directly from db - document_updated = db_collection.find_one( {"_id": doc_oid } ) - document_out = marshal( document_updated, models["model_doc_out"] ) + # ### get updated doc directly from db + # document_updated = db_collection.find_one( {"_id": doc_oid } ) + # document_out = marshal( document_updated, models["model_doc_out"] ) - ### update needs_rebuild - db_collection.update_one( {"_id": doc_oid }, { "$set" : {"log.needs_rebuild" : True} } ) + # ### update needs_rebuild + # db_collection.update_one( {"_id": doc_oid }, { "$set" : {"log.needs_rebuild" : True} } ) - ### check if prj is buildable & update - is_buildable = check_if_prj_is_buildable(document_out) - log.debug( "is_buildable : %s", is_buildable ) - db_collection.update_one( {"_id": doc_oid }, { "$set" : {"log.is_buildable" : is_buildable } } ) + # ### check if prj is buildable & update + # is_buildable = check_if_prj_is_buildable(document_out) + # log.debug( "is_buildable : %s", is_buildable ) + # db_collection.update_one( {"_id": doc_oid }, { "$set" : {"log.is_buildable" : is_buildable } } ) ### get updated doc directly from db @@ -450,9 +450,6 @@ def Query_db_update ( - - - else : ### no document / empty response response_code = 404 diff --git a/auth_api/_models/models_generic.py b/auth_api/_models/models_generic.py index 93c1c0c..efebb5c 100644 --- a/auth_api/_models/models_generic.py +++ b/auth_api/_models/models_generic.py @@ -14,7 +14,7 @@ ### import data serializers from auth_api._serializers.schema_logs import * -from auth_api._serializers.schema_generic import * +from auth_api._serializers.schema_generic import * from auth_api._serializers.schema_users import * @@ -264,163 +264,6 @@ def create_model_uses( ns_, return uses -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -### MODEL / DATASETS -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -def create_model_dataset( ns_, - model_name = "Datasets" , - include_fav = False, - include_dmf_open_level = False , - display_fullname = False , - schema = "prj", - is_light = False, - ) : - """ - Dataset model (one) - """ - - - if is_light : - model_dataset = { - "oid_"+schema : oid_dict[schema]["field"], - # 'added_at' : added_at, - # 'added_by' : added_by, - } - else : - model_dataset = { - "oid_"+schema : oid_dict[schema]["field"], - 'added_at' : added_at, - 'added_by' : added_by, - } - - if include_fav == True : - model_dataset["is_fav"] = is_fav - - if include_dmf_open_level == True and schema in ["dmf","dsr"] : - model_dataset["open_level"] = open_level - - dataset = fields.Nested( - ns_.model( schema.title()+"_ref", model_dataset ) - ) - - return dataset - - -def create_model_datasets( ns_, - model_name = "Datasets" , - include_fav = False, - include_dmf_open_level = False , - display_fullname = False , - schema_list = ["prj","dmt","dmf","dsi","dsr","rec","dso","tag","func"], - is_light = False, - ) : - """ - Datasets model (nested) - """ - - datasets_dict = {} - - for schema in schema_list : - - dataset = create_model_dataset( ns_, - model_name = model_name, - include_fav = include_fav, - include_dmf_open_level = include_dmf_open_level, - display_fullname = display_fullname, - schema = schema, - is_light = is_light - ) - - dataset_list = fields.List( - dataset, - description = "List of {}s on this document".format(oid_dict[schema]["fullname"]), - default = [] - ) - - datasets_dict[schema+"_list"] = dataset_list - - datasets = fields.Nested( - ns_.model( model_name, datasets_dict ) - ) - - return datasets - - -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -### MODEL / MAPPING -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -def create_model_mappings( ns_, - model_name = "Mapping" , - schema_list = ["dsi_to_dmt", "map_func", "map_rec", "dmf_to_open_level"], - ) : - """ - Mapping model - mapping the relation between a document and another - """ - - mapping_dict = {} - - for schema in schema_list : - - ### TO DO - - model_mapping = mapping_oid_dict[schema] - # model_mapping['added_at'] = added_at - # model_mapping['added_by'] = added_by - - # if schema == "dsi_to_dmf" : - # model_mapping['visible_dmf_list'] = fields.List( - # oid_dmf, - # description = "visible dmf list" - # ) - - mapping = fields.Nested( - ns_.model( schema.title(), model_mapping ), - description = "mapping between {}".format(schema), - ) - - mapping_list = fields.List( - mapping, - description = "List of {}s on this document".format(schema), - default = [] - ) - - mapping_dict[schema] = mapping_list - - mappings = fields.Nested( - ns_.model( model_name, mapping_dict ) - ) - - return mappings - -def create_model_field_update_mapping( ns_, - model_name = "Mapping_update" - ): - - """ - Field update - """ - - mapping_update = ns_.model(model_name, update_mapping ) - - return mapping_update - - -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -### MODEL / SOLIDIFY -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -def create_model_solidify_run_params( ns_, - model_name = "Solidify_run_params" - ): - - """ - Field update - """ - - solidify_run_params = ns_.model(model_name, run_recipe ) - - return solidify_run_params - ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### ### MODEL / MODIFICATIONS LOG ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### diff --git a/auth_api/_models/models_user.py b/auth_api/_models/models_user.py index 89ae585..0192544 100644 --- a/auth_api/_models/models_user.py +++ b/auth_api/_models/models_user.py @@ -152,34 +152,26 @@ class User_infos : def __init__(self, ns_) : - model_type = "Usr" + model_type = "Usr" ### SELF MODULES - self._id = oid_field - self.basic_infos = create_model_basic_infos( ns_, model_name=model_type+"_infos", is_user_infos=True) - self.basic_infos_light = create_model_basic_infos( ns_, model_name=model_type+"_infos", is_user_infos=True, is_user_light=True) - self.public_auth = create_model_public_auth( ns_, model_name=model_type+"_public_auth") - self.specs = create_model_specs( ns_, model_name=model_type+"_specs") - self.log = create_model_log( ns_, model_name=model_type+"_log", include_counts=True, counts_name="login_count") - self.modif_log = create_model_modif_log( ns_, model_name=model_type+"_modif_log") + self._id = oid_field + self.basic_infos = create_model_basic_infos( ns_, model_name=model_type+"_infos", is_user_infos=True) + self.basic_infos_light = create_model_basic_infos( ns_, model_name=model_type+"_infos", is_user_infos=True, is_user_light=True) + self.public_auth = create_model_public_auth( ns_, model_name=model_type+"_public_auth") + self.specs = create_model_specs( ns_, model_name=model_type+"_specs") + self.log = create_model_log( ns_, model_name=model_type+"_log", include_counts=True, counts_name="login_count") + self.modif_log = create_model_modif_log( ns_, model_name=model_type+"_modif_log") - self.datasets = create_model_datasets( ns_, model_name=model_type+"_datasets", include_fav=True, schema_list=["prj","dmt", "dmf","dsi","rec","tag"]) - self.datasets_light = create_model_datasets( ns_, model_name=model_type+"_datasets", include_fav=True, schema_list=["prj","dmt", "dmf","dsi","rec","tag"], is_light=True ) + self.team = create_model_team( ns_, model_name=model_type+"_team") + self.team_light = create_model_team( ns_, model_name=model_type+"_team", is_light=True) - self.team = create_model_team( ns_, model_name=model_type+"_team") - self.team_light = create_model_team( ns_, model_name=model_type+"_team", is_light=True) - - self.profile = create_model_profile( ns_, model_name=model_type+"_profile") + self.profile = create_model_profile( ns_, model_name=model_type+"_profile") self.professional_infos = create_professional_infos(ns_, model_name=model_type+"_professionnal_infos") - self.auth_in = create_model_auth( ns_, model_type+"_authorizations", schema=user_auth_in) - # self.auth_in = fields.Nested( - # ns_.model(model_type+"_authorizations", user_auth_in ) - # ) - self.auth_out = create_model_auth( ns_, model_type+"_authorizations", schema=user_auth_out) - # self.auth_out = fields.Nested( - # ns_.model(model_type+"_authorizations", user_auth_out ) - # ) + self.auth_in = create_model_auth( ns_, model_type+"_authorizations", schema=user_auth_in) + self.auth_out = create_model_auth( ns_, model_type+"_authorizations", schema=user_auth_out) + self.model_id = { @@ -196,13 +188,13 @@ def __init__(self, ns_) : } self.model_in = { 'modif_log' : self.modif_log , - "datasets" : self.datasets , - 'profile' : self.profile, + # "datasets" : self.datasets , + 'profile' : self.profile, 'professional_infos' : self.professional_infos, } self.spec_auth_log = { - 'public_auth' : self.public_auth, - 'specs' : self.specs , + 'public_auth' : self.public_auth, + 'specs' : self.specs , 'log' : self.log , } self.model_min = { @@ -225,9 +217,7 @@ def __init__(self, ns_) : self.model_team_light = { 'team' : self.team_light, } - self.model_datasets_light = { - 'datasets' : self.datasets_light, - } + ### IN / complete data to enter in DB self.mod_complete_in = ns_.model(model_type+"_in", @@ -262,7 +252,7 @@ def __init__(self, ns_) : { **self.model_min_light, **self.model_id, - **self.model_datasets_light + # **self.model_datasets_light } ) diff --git a/auth_api/_parsers/__init__.py b/auth_api/_parsers/__init__.py index 74f80a7..3d573dc 100644 --- a/auth_api/_parsers/__init__.py +++ b/auth_api/_parsers/__init__.py @@ -5,7 +5,3 @@ """ from .parser_classes import * - -# from .parser_files import * -# from .parser_pagination import * -# from .parser_queries import * \ No newline at end of file diff --git a/auth_api/_parsers/parser_classes.py b/auth_api/_parsers/parser_classes.py index 41ac84a..8052a45 100644 --- a/auth_api/_parsers/parser_classes.py +++ b/auth_api/_parsers/parser_classes.py @@ -26,9 +26,9 @@ class RequestParserBuilder : def __init__( self, add_pagination = False, - add_queries = False, + add_queries = False, add_data_query = False, - add_files = False, + add_files = False, ) : self.baseParser = reqparse.RequestParser() @@ -55,22 +55,6 @@ def __init__( self, if add_queries : - # self.baseParser.add_argument( - # 'q_title', - # # action='append', ### multiple values - # type=str, - # required=False, - # help='find documents matching this string in the title', - # # location = 'values' - # ) - # self.baseParser.add_argument( - # 'q_description', - # # action='append', ### multiple values - # type=str, - # required=False, - # help='find documents matching this string in the description', - # # location = 'values' - # ) self.baseParser.add_argument( 'search_for', action='append', @@ -261,41 +245,7 @@ def __init__( self, help='Separator', location = 'values' ) - # self.baseParser.add_argument( - # 'form_file', - # type=FileStorage, - # location='form', - # required=False, - # help='any data file : tsv, csv, xml, xls, xlsx', - # ) - # self.baseParser.add_argument( - # 'xls_file', - # type=FileStorage, - # location='files', - # required=False, - # help='XLS file', - # ) - # self.baseParser.add_argument( - # 'xlsx_file', - # type=FileStorage, - # location='files', - # required=False, - # help='XLSX file', - # ) - # self.baseParser.add_argument( - # 'csv_file', - # type=FileStorage, - # location='files', - # required=False, - # help='CSV file', - # ) - # self.baseParser.add_argument( - # 'xml_file', - # type=FileStorage, - # location='files', - # required=False, - # help='XML file', - # ) + for field in [ 'title', 'description', @@ -325,7 +275,6 @@ def __init__( self, choices=doc_src_type_list, default='csv' ) - @property def get_parser (self) : @@ -348,6 +297,5 @@ def get_parser (self) : q_pag_args = RequestParserBuilder(add_pagination=True, add_queries=True) query_pag_args = q_pag_args.get_parser - -q_data_dso = RequestParserBuilder(add_pagination=True, add_data_query=True) -query_data_dso_arguments = q_data_dso.get_parser \ No newline at end of file +# q_data_dso = RequestParserBuilder(add_pagination=True, add_data_query=True) +# query_data_dso_arguments = q_data_dso.get_parser \ No newline at end of file diff --git a/auth_api/_parsers/parser_files.py b/auth_api/_parsers/parser_files.py deleted file mode 100644 index 96ff511..0000000 --- a/auth_api/_parsers/parser_files.py +++ /dev/null @@ -1,40 +0,0 @@ -# # -*- encoding: utf-8 -*- - -# """ -# parser_files.py -# """ - -# from log_config import log, pformat - -# from werkzeug.datastructures import FileStorage -# from flask_restplus import reqparse - -# log.debug("~ ~ ~ loading parser_files.py ...") - - -# file_parser = reqparse.RequestParser() -# file_parser.add_argument('data_file', -# type=FileStorage, -# location='files', -# required=True, -# help='any data file : csv, xml, xls, xlsx') -# # file_parser.add_argument('xls_file', -# # type=FileStorage, -# # location='files', -# # required=False, -# # help='XLS file') -# # file_parser.add_argument('xlsx_file', -# # type=FileStorage, -# # location='files', -# # required=False, -# # help='XLSX file') -# # file_parser.add_argument('csv_file', -# # type=FileStorage, -# # location='files', -# # required=False, -# # help='CSV file') -# # file_parser.add_argument('xml_file', -# # type=FileStorage, -# # location='files', -# # required=False, -# # help='XML file') \ No newline at end of file diff --git a/auth_api/_parsers/parser_pagination.py b/auth_api/_parsers/parser_pagination.py deleted file mode 100644 index 792b778..0000000 --- a/auth_api/_parsers/parser_pagination.py +++ /dev/null @@ -1,36 +0,0 @@ -# # -*- encoding: utf-8 -*- - -# """ -# parser_pagination.py -# """ - -# from log_config import log, pformat - -# from flask_restplus import reqparse - -# log.debug("~ ~ ~ loading parser_pagination.py ...") - - -# pagination_arguments = reqparse.RequestParser() -# pagination_arguments.add_argument( -# 'page', -# type=int, -# required=False, -# default=1, -# help='Page number' -# ) -# # pagination_arguments.add_argument( -# # 'bool', -# # type=bool, -# # required=False, -# # default=True, -# # help='Page number' -# # ) -# pagination_arguments.add_argument( -# 'per_page', -# type=int, -# required=False, -# choices=[2, 10, 20, 30, 40, 50], -# default=10, -# help='Results per page {error_msg}' -# ) \ No newline at end of file diff --git a/auth_api/_parsers/parser_queries.py b/auth_api/_parsers/parser_queries.py deleted file mode 100644 index 0871834..0000000 --- a/auth_api/_parsers/parser_queries.py +++ /dev/null @@ -1,51 +0,0 @@ -# # -*- encoding: utf-8 -*- - -# """ -# parser_queries.py -# """ - -# from log_config import log, pformat - -# from flask_restplus import reqparse - -# log.debug("~ ~ ~ loading parser_queries.py ...") - -# ### cf : https://flask-restplus.readthedocs.io/en/stable/parsing.html - -# query_arguments = reqparse.RequestParser() -# query_arguments.add_argument( -# 'q_title', -# action='append', -# type=str, -# required=False, -# help='find documents matching this string in the title' -# ) -# query_arguments.add_argument( -# 'q_description', -# action='append', -# type=str, -# required=False, -# help='find documents matching this string in the description' -# ) -# query_arguments.add_argument( -# 'tags', -# action='split', -# type=str, -# required=False, -# help='find documents matching this list of tags oid' -# ) -# query_arguments.add_argument( -# 'oids', -# action='split', -# type=str, -# required=False, -# help='find documents matching this list of oid to find' -# ) -# query_arguments.add_argument( -# 'only_stats', -# type=bool, -# required=False, -# default=False, -# help='just retrieve the stats of the result' -# ) - diff --git a/auth_api/_serializers/schema_generic.py b/auth_api/_serializers/schema_generic.py index ac98e0c..9e5bd56 100644 --- a/auth_api/_serializers/schema_generic.py +++ b/auth_api/_serializers/schema_generic.py @@ -25,14 +25,14 @@ def format(self, value): ### generic info for updates ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### generic_data = fields.String( - description = "data about a document", + description = "data about a document", attribute = "data", example = "new data", default = 'a new data', required = True, ) -url_link = fields.String( - description = "generic url_link", +url_link = fields.String( + description = "generic url_link", attribute = "url_link", example = "my-url-link", default = '', @@ -43,31 +43,31 @@ def format(self, value): ### for document updates ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### field_raw = fields.Raw( - description = "raw data about a document", + description = "raw data about a document", attribute = "field_raw", example = "raw data", default = 'a new raw data', required = True, ) field_value = fields.Raw( - description = "data about a document", + description = "data about a document", attribute = "data", example = "new data", default = 'a new data', required = True, ) field_to_update = fields.String( - description = "data about a document", + description = "data about a document", attribute = "field_to_update", example = "infos.title", default = 'a new data', required = True, ) add_to_list = fields.String( - description = "data about a document", + description = "data about a document", attribute = "add_to_list", example = False, - enum = update_types_list, + enum = update_types_list, default = False, ) @@ -75,21 +75,21 @@ def format(self, value): ### basic informations about a document : project / licence / oid ... ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### title = fields.String( - description = "title of the document", + description = "title of the document", attribute = "title", example = "my-title", default = 'title', required = True, ) descript = fields.String( - description = "description of the document", + description = "description of the document", attribute = "description", example = "my-description", default = 'description', required = False, ) licence = fields.String( - description = "licence of the document", + description = "licence of the document", attribute = "licence", example = "MIT", default = 'MIT', @@ -97,7 +97,7 @@ def format(self, value): required = True, ) open_level = fields.String( - description = "open level of the document", + description = "open level of the document", attribute = "open_level", example = "commons", default = 'open_data', @@ -105,7 +105,7 @@ def format(self, value): required = False, ) open_level_edit = fields.String( - description = "open level of the document for edit", + description = "open level of the document for edit", attribute = "open_level_edit", example = "collective", default = 'collective', @@ -113,7 +113,7 @@ def format(self, value): required = True, ) open_level_show = fields.String( - description = "open level of the document for show", + description = "open level of the document for show", attribute = "open_level_show", example = "commons", default = 'open_data', @@ -121,7 +121,7 @@ def format(self, value): required = True, ) is_standard = fields.Boolean( - description = "is it standard document ?", + description = "is it standard document ?", attribute = "is_standard", example = True, required = False, @@ -132,65 +132,33 @@ def format(self, value): ### multilanguage ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### locale = fields.String( - description = "locale language code", + description = "locale language code", attribute = "locale", example = "fr", default = 'en', required = False, ) field_to_translate = fields.String( - description = "code of the field to translatee", + description = "code of the field to translatee", attribute = "field_to_translate", example = "infos.title", default = 'infos.title', required = False, ) text_translated = fields.String( - description = "text to translate", + description = "text to translate", attribute = "text_translated", example = "my-translation", default = '', required = False, ) -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -### sources DSI -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -src_link = fields.String( - description = "source link of the document", - attribute = "src_link", - example = "my-link-to-my-source", - default = '', - required = False, - ) -src_type = fields.String( - description = "source type of the document", - attribute = "src_type", - example = "csv", - default = "", - required = False, - ) -src_parser = fields.String( - description = "parser for an API response", - attribute = "src_parser", - example = "/example/of/path", - default = "/", - required = False, - ) -src_sep = fields.String( - description = "separator for a CSV file", - attribute = "src_sep", - example = ",", - default = ",", - enum = authorized_separators, - required = False, - ) ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### ### tags ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### tag = fields.String( - description = "tag about the document", + description = "tag about the document", attribute = "tag", example = "my-tag", # default = '', @@ -198,7 +166,7 @@ def format(self, value): ) tags_list = fields.List( tag, - description = "list of tags about the document", + description = "list of tags about the document", attribute = "tags_list", default = [] ) @@ -212,482 +180,115 @@ class IdField(fields.Raw): def format(self, value): return str(value) -oid_field = IdField( - description = "data about a document", +oid_field = IdField( + description = "data about a document", attribute = "_id", example = "ObjectId('5b841ac70a82863ff21fd4d7')", ) -oid = IdField( -# oid = fields.String( - description = "oid of a document", +oid = IdField( + description = "oid of a document", attribute = "oid", example = "ObjectId('5b841ac70a82863ff21fd4d7')", required = True, ) -doc_id = fields.String( - description = "oid of a document as string", +doc_id = fields.String( + description = "oid of a document as string", attribute = "doc_id", example = "5b841ac70a82863ff21fd4d7", required = True, ) -oid_usr = IdField( -# oid_usr = fields.String( - description = "oid of an user", +oid_usr = IdField( + description = "oid of an user", attribute = "oid_usr", example = "ObjectId('5b841ac70a82863ff21fd4d7')", required = True, ) created_by = IdField( -# created_by = fields.String( - description = "oid of an user", + description = "oid of an user", attribute = "created_by", example = "ObjectId('5b841ac70a82863ff21fd4d7')", required = True, ) used_by = IdField( -# used_by = fields.String( - description = "oid of a document", + description = "oid of a document", attribute = "used_by", example = "ObjectId('5b841ac70a82863ff21fd4d7')", required = True, ) modified_by = IdField( -# modified_by = fields.String( - description = "oid of an user", + description = "oid of an user", attribute = "modified_by", example = "ObjectId('5b841ac70a82863ff21fd4d7')", required = True, ) added_by = IdField( -# added_by = fields.String( - description = "oid of an user", + description = "oid of an user", attribute = "added_by", example = "ObjectId('5b841ac70a82863ff21fd4d7')", required = True, ) used_as = fields.String( - description = "category of use", + description = "category of use", attribute = "used_as", enumerate = doc_type_list, example = "prj", required = True, ) -oid_prj = IdField( -# oid_prj = fields.String( - description = "oid of a project", - attribute = "oid_prj", - example = "ObjectId('5b841ac70a82863ff21fd4d7')", - required = True, - ) -oid_dmf = IdField( -# oid_dmf = fields.String( - description = "oid of a datamodel field", - attribute = "oid_dmf", - example = "ObjectId('5b841ac70a82863ff21fd4d7')", - required = True, - ) -oid_dmt = IdField( -# oid_dmt = fields.String( - description = "oid of a datamodel template", - attribute = "oid_dmt", - example = "ObjectId('5b841ac70a82863ff21fd4d7')", - required = True, - ) -oid_dsi = IdField( -# oid_dsi = fields.String( - description = "oid of a dataset input", - attribute = "oid_dsi", - example = "ObjectId('5b841ac70a82863ff21fd4d7')", - required = True, - ) -oid_dsr = IdField( -# oid_dsr = fields.String( - description = "oid of a dataset raw", - attribute = "oid_dsr", - example = "ObjectId('5b841ac70a82863ff21fd4d7')", - required = True, - ) -oid_dso = IdField( -# oid_dso = fields.String( - description = "oid of a dataset output", - attribute = "oid_dso", - example = "ObjectId('5b841ac70a82863ff21fd4d7')", - required = True, - ) -oid_rec = IdField( -# oid_rec = fields.String( - description = "oid of a recipe", - attribute = "oid_rec", - example = "ObjectId('5b841ac70a82863ff21fd4d7')", - required = True, - ) -oid_tag = IdField( -# oid_tag = fields.String( - description = "oid of a tag", - attribute = "oid_tag", - example = "ObjectId('5b841ac70a82863ff21fd4d7')", - required = True, - ) oid_fld = IdField( -# oid_fld = fields.String( - description = "oid of a field", + description = "oid of a field", attribute = "oid_fld", example = "ObjectId('5b841ac70a82863ff21fd4d7')", required = True, ) -oid_func = IdField( -# oid_func = fields.String( - description = "oid of a function", - attribute = "oid_func", - example = "ObjectId('5b841ac70a82863ff21fd4d7')", - required = True, - ) ### store a correspondance dict of oids... oid_dict = { "oid" : { "field" : oid , "fullname" : "oid" } , "usr" : { "field" : oid_usr , "fullname" : "user" } , - "prj" : { "field" : oid_prj , "fullname" : "project" } , - "dmt" : { "field" : oid_dmt , "fullname" : "datamodel_template" } , - "dmf" : { "field" : oid_dmf , "fullname" : "datamodel_field" } , - "dsi" : { "field" : oid_dsi , "fullname" : "dataset_input" } , - "dsr" : { "field" : oid_dsr , "fullname" : "dataset_raw" } , - "rec" : { "field" : oid_rec , "fullname" : "recipe" } , - "func" : { "field" : oid_func ,"fullname" : "function" } , - "dso" : { "field" : oid_dso , "fullname" : "dataset_output" } , - "fld" : { "field" : oid_fld , "fullname" : "field" } , - "tag" : { "field" : oid_tag , "fullname" : "tag" } , } -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -### for recipes -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -is_complex_rec = fields.Boolean( - description = "does the recipe need to load the project ?", - attribute = "is_complex_rec", - example = False, - required = False, - default = False, - ) -# need_load_prj = fields.Boolean( -# description = "does the recipe need to load the project ?", -# attribute = "need_load_prj", -# example = False, -# required = False, -# default = False, -# ) -# need_load_dmt = fields.Boolean( -# description = "does the recipe need to load the datamodel ?", -# attribute = "need_load_dmt", -# example = False, -# required = False, -# default = False, -# ) -# need_load_dsi = fields.Boolean( -# description = "does the recipe need to load the dataset input(s) ?", -# attribute = "need_load_dsi", -# example = False, -# required = False, -# default = False, -# ) - -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -### for mappings -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -dsi_header = fields.String( - description = "index of a column within a dataset input", - attribute = "dsi_header", - example = "my_dsi_header", - required = False, - ) - -is_mapping = fields.Boolean( - description = "is it an update in mapping field ?", - attribute = "is_mapping", - example = True, - required = False, - default = False, - ) -del_mapping = fields.Boolean( - description = "is it to delete an entry from mapping ?", - attribute = "del_mapping", - example = True, - required = False, - default = False, - ) - -mapping_field = fields.String( - description = "field to map", - attribute = "mapping_field", - example = False, - enum = mapping_fields, - default = False, - ) -id_dmt = fields.String( - description = "oid of a document dmt as string", - attribute = "id_dmt", - example = "5b841ac70a82863ff21fd4d7", - required = False, - ) -id_dmf = fields.String( - description = "oid of a document dmf as string", - attribute = "id_dmf", - example = "5b841ac70a82863ff21fd4d7", - required = False, - ) -id_dsi = fields.String( - description = "oid of a document dsi as string", - attribute = "id_dsi", - example = "5b841ac70a82863ff21fd4d7", - required = False, - ) -id_rec = fields.String( - description = "oid of a document rec as string", - attribute = "id_rec", - example = "5b841ac70a82863ff21fd4d7", - required = False, - ) -id_func = fields.String( - description = "oid of a document func as string", - attribute = "id_func", - example = "5b841ac70a82863ff21fd4d7", - required = False, - ) - - -rec_params = fields.Raw( - description = "raw parameters for a recipe", - attribute = "rec_params", - example = "raw data", - default = 'a new raw map parameters', - required = False, - ) -function_class = fields.String( - description = "path to load the class from _core.solidify folder", - attribute = "function_class", - example = "geoloc", - required = False, - ) -function_runner = fields.String( - description = "name of the function in function_class", - attribute = "function_runner", - example = "geoloc_prj", - required = False, - ) -default_values = fields.Raw( - description = "default values for parameters of a recipe", - attribute = "default_values", - example = "{ '' : '' }", - default = 'default values for parametesparameters', - required = False, - ) - - -update_mapping = { - "is_mapping" : is_mapping, - "del_mapping" : del_mapping, - "field_to_update" : field_to_update, - # "mapping_field" : mapping_field, - "id_dmt" : id_dmt, - "id_dmf" : id_dmf, - "id_dsi" : id_dsi, - "id_rec" : id_rec, - # "id_func" : id_func, - "open_level_show" : open_level_show, - "dsi_header" : dsi_header, - "rec_params" : rec_params -} - -mapping_oid_dict = { - - "dmf_to_open_level" : { - ### target dmf - "oid_dmf" : oid_dmf, - ### target open_level - "open_level_show" : open_level_show, - }, - "dsi_to_dmf" : { - ### src dsi - "oid_dsi" : oid_dsi, - "dsi_header" : dsi_header, - ### target dmf - "oid_dmf" : oid_dmf, - } , - "map_rec" : { - ### src rec - "oid_rec" : oid_rec, - ### rec_params : {} - "rec_params" : rec_params - } , - "map_func" : { - ### rec_params : {} - "function_class" : function_class, - "function_runner" : function_runner, - "default_values" : default_values - } , - -} - ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### ### edit auth for a document ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### guests_can_see = fields.Boolean( - description = "can guests see the document ?", + description = "can guests see the document ?", attribute = "guests_can_see", example = True, required = True, default = True, ) guests_can_edit = fields.Boolean( - description = "can guests edit the document ?", + description = "can guests edit the document ?", attribute = "guests_can_edit", example = False, required = True, default = False, ) edit_auth = fields.String( - description = "edit auth of an user", + description = "edit auth of an user", enum = user_edit_auth, example = "owner", required = False, attribute = "edit_auth", default = "editor" ) - -# public_auth = { -# "open_level" : open_level, -# "guests_can_see" : guests_can_see, -# "guests_can_edit" : guests_can_edit -# } + public_auth = { "open_level_edit" : open_level_edit, "open_level_show" : open_level_show, } -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -### data_raw for dsi - dso - dmf - tag -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -f_cell = fields.String( - description = "content of a field", - attribute = "f_cell", - example = "data", - required = False, - ) -f_title = fields.String( - description = "title of the field", - attribute = "f_title", - example = "header title", - required = False, - ) -f_code = fields.String( - description = "code of the field", - attribute = "f_code", - example = "data code", - required = False, - ) -f_object = fields.String( - description = "object of the field", - attribute = "f_object", - example = "data object", - required = False, - ) -f_type = fields.String( - description = "type of the field", - attribute = "f_type", - enum = dmf_types_list, - example = "data type", - required = False, - ) -f_comments = fields.String( - description = "comments about the field", - attribute = "f_comments", - example = "data comments", - required = False, - ) -f_is_required = fields.Boolean( - description = "is the field required ?", - attribute = "f_is_required", - example = False, - required = False, - default = False, - ) - -f_coll_header_val = fields.String( - description = "columns headers value", - attribute = "f_coll_header_val", - ) -f_coll_header_text = fields.String( - description = "columns headers text", - attribute = "f_coll_header_text", - ) -# f_coll_headers = fields.List( -# f_coll_header, -# example = ["my_header"], -# attribute = "f_coll_headers", -# default = [] -# ) -f_data = fields.Raw( - description = "raw data about a document", - attribute = "f_data", - example = "raw data", - default = 'a new raw data', - required = True, - ) - -f_basics_tag = { - "f_code" : f_code, - "f_object" : f_object, - "f_comments" : f_comments, -} -f_basics_dmf = { - "f_code" : f_code, - "f_object" : f_object, - "f_type" : f_type, - "f_comments" : f_comments, - "f_is_required" : f_is_required, -} -f_headers_ds = { - "f_coll_header_val" : f_coll_header_val, - "f_coll_header_text" : f_coll_header_text, -} -f_headers_dso = { - "f_title" : f_title, - "f_code" : f_code, - "f_type" : f_type, - "open_level_show" : open_level_show, - "oid_dmf" : oid_dmf, -} - -f_basics_rec = { - "f_code" : f_code, - "f_object" : f_object, - "f_comments" : f_comments, - "field_raw" : field_raw, -} - -# f_basics_dsi_dsr_dso = { -# "f_data" : f_code, -# "f_col_headers" : f_code, -# } -# f_basics_dsr = { -# "f_data" : f_code, -# "f_col_headers" : f_code, -# } -# f_basics_dso = { -# "f_data" : f_code, -# "f_col_headers" : f_code, -# } ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### ### log basics ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### is_running = fields.Boolean( - description = "is the project currently running ?", + description = "is the project currently running ?", attribute = "is_running", example = False, required = True, @@ -695,7 +296,7 @@ def format(self, value): ) is_loaded = fields.Boolean( - description = "is the project currently loaded ?", + description = "is the project currently loaded ?", attribute = "is_loaded", example = False, required = False, @@ -703,35 +304,20 @@ def format(self, value): ) is_linked_to_src = fields.Boolean( - description = "is the project currently linked to the source ?", + description = "is the project currently linked to the source ?", attribute = "is_linked_to_src", example = False, required = False, default = False, ) -is_buildable = fields.Boolean( - description = "is the project buildable as a dso ?", - attribute = "is_buildable", - example = False, - required = False, - default = False, - ) -needs_rebuild = fields.Boolean( - description = "does the project need to be rebuilt as a dso ?", - attribute = "needs_rebuild", - example = False, - required = False, - default = False, - ) - ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### ### specs basics ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### doc_type = fields.String( - description = "category of a document", + description = "category of a document", attribute = "doc_type", - enum = doc_type_list, + enum = doc_type_list, example = "usr", # default = 'usr', required = True, @@ -745,32 +331,19 @@ def format(self, value): } doc_basics = { - "title" : title, + "title" : title, "description" : descript, } doc_basics_licence = { - "title" : title, - "licence" : licence, + "title" : title, + "licence" : licence, "description" : descript, } -# doc_basics_openlevel = { -# "title" : title, -# "open_level" : open_level, -# "description" : descript, -# } - -# doc_basics_licence_openlevel = { -# "title" : title, -# "licence" : licence, -# "open_level" : open_level, -# "description" : descript, -# } - open_level_edit_show = { "open_level_edit" : open_level_edit, - "open_level_show" : open_level_show, + "open_level_show" : open_level_show, } open_level_edit_ = { "open_level_edit" : open_level_edit, @@ -790,14 +363,3 @@ def format(self, value): "field_value" : field_value, } - -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -### preformat some generic fields -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -run_recipe = { - "id_rec" : id_rec, - # "is_complex_rec" : is_complex_rec, - # "need_load_prj" : need_load_prj, - # "need_load_dmt" : need_load_dmt, - # "need_load_dsi" : need_load_dsi, -} \ No newline at end of file diff --git a/auth_api/_serializers/schema_logs.py b/auth_api/_serializers/schema_logs.py index a95fc09..0967d70 100644 --- a/auth_api/_serializers/schema_logs.py +++ b/auth_api/_serializers/schema_logs.py @@ -73,37 +73,8 @@ required = False, ) -# used_by = fields.String( -# description = "oid of a document", -# attribute = "used_by", -# example = "5b461ed90a82867e7b114f44", -# required = True, -# ) -# modified_by = fields.String( -# description = "oid of an user", -# attribute = "modified_by", -# example = "5b461ed90a82867e7b114f44", -# required = True, -# ) -# added_by = fields.String( -# description = "oid of an user", -# attribute = "added_by", -# example = "5b461ed90a82867e7b114f44", -# required = True, -# ) - ### FOR GENERIC MODELS -# modification = { -# "modif_at" : modified_at, -# "modif_for" : modified_for -# } - -# modification_by = { -# "modif_at" : modified_at, -# "modif_for" : modified_for, -# "modif_by" : oid_usr -# } modification_full = { "modif_at" : modified_at, @@ -111,8 +82,3 @@ "modif_by" : oid_usr, "modif_val" : modified_val, } - -# doc_uses = { -# "used_by" : used_by, -# "used_at" : used_at, -# } \ No newline at end of file diff --git a/auth_api/_serializers/schema_pagination.py b/auth_api/_serializers/schema_pagination.py index 4539fa9..61773e8 100644 --- a/auth_api/_serializers/schema_pagination.py +++ b/auth_api/_serializers/schema_pagination.py @@ -17,7 +17,7 @@ 'page' = fields.Integer(description='Number of this page of results') 'pages' = fields.Integer(description='Total number of pages of results') -'per_page' = fields.Integer(description='Number of items per page of results') +'per_page' = fields.Integer(description='Number of items per page of results') 'total' = fields.Integer(description='Total number of results') -'has_next' = fields.Boolean() -'has_prev' = fields.Boolean() \ No newline at end of file +'has_next' = fields.Boolean() +'has_prev' = fields.Boolean() \ No newline at end of file diff --git a/auth_api/_serializers/schema_users.py b/auth_api/_serializers/schema_users.py index 776b462..6c750ed 100644 --- a/auth_api/_serializers/schema_users.py +++ b/auth_api/_serializers/schema_users.py @@ -19,33 +19,33 @@ ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### ### basic informations about a user ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -name = fields.String( +name = fields.String( description = "name of the user", attribute = "name", example = "Elinor", default = 'Anonymous User', required = False, ) -pseudo = fields.String( +pseudo = fields.String( description = "pseudo of the user", attribute = "pseudo", example = "Coco", default = 'Anonymous User', required = False, ) -surname = fields.String( +surname = fields.String( description = "surname of the user", attribute = "surname", example = "Ostrom", required = False, ) -email = fields.String( +email = fields.String( description = "email of the user", attribute = "email", example = "elinor.ostrom@emailna.co", ### uses https://www.mohmal.com for temporary emails required = True, ) -agreement = fields.Boolean( +agreement = fields.Boolean( description = "user has agreed to terms and conditions", attribute = "agreement", example = False, @@ -61,19 +61,19 @@ ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### ### auth ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -pwd = fields.String( +pwd = fields.String( description = "password of the user", attribute = "pwd", example = "a-very-common-password", required = True, ) -pwd_encrypt = fields.String( +pwd_encrypt = fields.String( description = "password of the user hashed from frontend with access_token", attribute = "pwd_encrypt", example = "hashed-common-password", required = False, ) -confirmed_usr = fields.Boolean( +confirmed_usr = fields.Boolean( description = "user has confirmed its account from his email", attribute = "conf_usr", example = False, @@ -87,7 +87,7 @@ required = False, default = False, ) -role = fields.String( +role = fields.String( description = "role / authorization level of the user", attribute = "role", example = "guest", @@ -95,13 +95,13 @@ default = "guest", required = True, ) -acc_tok = fields.String( +acc_tok = fields.String( description = "access token of user", attribute = "acc_tok", example = "a-json-web-access-token", default = "no_access_token", ) -refr_tok = fields.String( +refr_tok = fields.String( description = "refresh token of user", attribute = "refr_tok", example = "a-json-web-refresh-token", @@ -114,36 +114,19 @@ default = "no_old_refresh_token", required = False, ) -# edit_auth = fields.List( -# fields.String( -# description = "edit auth of an user", -# enum = user_actions_proj, -# ), -# required = False, -# attribute = "edit_auth", -# default = [] -# ) -# edit_auth = fields.String( -# description = "edit auth of an user", -# enum = user_edit_auth, -# example = "can_only_view", -# required = False, -# attribute = "edit_auth", -# default = [] -# ) ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### ### profile ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### language = fields.String( - description = "language preference", + description = "language preference", example = "en", attribute = "lang", default = "en", - required = True, + required = False, ) is_fav = fields.Boolean( - description = "is the document a favorite ?", + description = "is the document a favorite ?", attribute = "is_fav", example = False, required = True, @@ -154,19 +137,19 @@ ### professional infos ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### struct_name = fields.String( - description = "name of the user's structure", + description = "name of the user's structure", attribute = "struct_name", required = True, ) struct_profile = fields.String( - description = "profile of the structure", + description = "profile of the structure", attribute = "struct_profile", example = "public_state", - enum = user_structure, + enum = user_structure, required = False, ) struct_url = fields.String( - description = "structure url link", + description = "structure url link", attribute = "struct_url", example = "my-url-link", default = '', @@ -174,8 +157,8 @@ ) usr_profile = fields.String( - description = "profiles of the user", - enum = user_profiles, + description = "profiles of the user", + enum = user_profiles, ) usr_profiles = fields.List( usr_profile, @@ -185,8 +168,8 @@ ) usr_view = fields.String( - description = "view of the user : which collections are visible in front", - enum = user_view, + description = "view of the user : which collections are visible in front", + enum = user_view, attribute = "usr_view", default = 'minimal', ) @@ -199,11 +182,11 @@ } user_identity = { - "email" : email, + "email" : email, } user_pwd = { - "pwd" : pwd, + "pwd" : pwd, } user_pwd_encrypted = { "pwd_encrypt" : pwd_encrypt, @@ -220,7 +203,7 @@ user_basics = { "name" : name, - "surname" : surname, + "surname" : surname, "email" : email, "pseudo" : pseudo, } diff --git a/auth_api/api/__init__.py b/auth_api/api/__init__.py index 19f74e6..ebcd6f5 100644 --- a/auth_api/api/__init__.py +++ b/auth_api/api/__init__.py @@ -7,6 +7,7 @@ from copy import copy, deepcopy from datetime import datetime, timedelta import json + from bson import json_util from bson.objectid import ObjectId from bson.json_util import dumps @@ -17,9 +18,9 @@ import numpy as np import requests -from flask import Blueprint, current_app as app, url_for, request, render_template +from flask import Blueprint, current_app as app, url_for, request, render_template -from werkzeug.security import generate_password_hash, check_password_hash +from werkzeug.security import generate_password_hash, check_password_hash from flask_restplus import Api, Namespace, Resource, fields, marshal, reqparse @@ -49,12 +50,12 @@ # cf : https://pythonhosted.org/pycrypto/Crypto.PublicKey.RSA._RSAobj-class.html#exportKey # cf : https://www.pycryptodome.org/en/latest/src/examples.html random_generator = Random.new().read -key_pair = RSA.generate(1024, random_generator) +key_pair = RSA.generate(1024, random_generator) private_key_str = key_pair.exportKey().decode("utf-8") log.debug("private_key_str : \n %s", pformat(private_key_str)) -public_key = key_pair.publickey() +public_key = key_pair.publickey() public_key_str = public_key.exportKey().decode("utf-8") log.debug("public_key_str : \n %s", pformat(public_key_str)) @@ -85,7 +86,7 @@ def RSAdecrypt(msg_encrypted): log.info("/ / \ \ plaintext : \n%s", plaintext) ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -### DEBUGGING CONFIRMAITON EMAIL +### DEBUGGING CONFIRMATION EMAIL ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### # from auth_api._auth import generate_confirmation_token @@ -102,17 +103,14 @@ def RSAdecrypt(msg_encrypted): from auth_api._auth.authorizations import authorizations as auth_check -from auth_api._auth import ( +from auth_api._auth import ( admin_required, current_user_required, confirm_email_required, guest_required, anonymous_required, renew_pwd_required, reset_pwd_required ) -from auth_api._parsers import * # pagination_arguments -# from auth_api._parsers.parser_pagination import * # pagination_arguments -# from auth_api._parsers.parser_queries import * # query_arguments -# from auth_api._parsers.parser_files import * # files_arguments +from auth_api._parsers import * # pagination_arguments -from auth_api._choices import bad_passwords, authorized_filetypes, authorized_mimetype +from auth_api._choices import bad_passwords, authorized_filetypes, authorized_mimetype from auth_api._core.utils import * # create_modif_log, secure_filename, allowed_file, return_payload # from auth_api._core.pandas_ops import * # create_modif_log, secure_filename, allowed_file diff --git a/auth_api/api/api_auth/endpoint_user_login.py b/auth_api/api/api_auth/endpoint_user_login.py index a0f71c5..8b01849 100644 --- a/auth_api/api/api_auth/endpoint_user_login.py +++ b/auth_api/api/api_auth/endpoint_user_login.py @@ -22,98 +22,6 @@ model_user_login_out = model_user.model_login_out -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### -### DECRYPTION -### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### - -# import Crypto -# from Crypto.PublicKey import RSA - - -# cf : https://github.com/berlincode/sjcl -# from sjcl import SJCL -# cyphertext = SJCL().encrypt( b"secret message to encrypt", "shared_secret") -# log.debug ("cyphertext : %s", cyphertext) -# cyphertext_decrypt = SJCL().decrypt(cyphertext, "shared_secret") -# log.debug ("cyphertext_decrypt : %s",cyphertext_decrypt ) - - - -# import base64 -# import urllib -# import binascii - -# from Crypto.Cipher import AES - -# # KEY = 'This is a key123' -# IV = 'IV_solidata' -# MODE = AES.MODE_CFB -# BLOCK_SIZE = 16 -# SEGMENT_SIZE = 128 - -# # cf : https://stackoverflow.com/questions/12524994/encrypt-decrypt-using-pycrypto-aes-256 - -# def decrypt_AES( cipher_text, key): - -# log.debug ("\ncipher_text : \n%s", pformat(cipher_text)) - -# decryption_suite = AES.new(key, AES.MODE_CBC, IV) -# plain_text = decryption_suite.decrypt(cipher_text) - -# # encodedEncrypted = urllib.parse.unquote(quotedEncodedEncrypted) -# # log.debug ("encodedEncrypted : %s", pformat(encodedEncrypted)) - -# # cipher = AES.new(key) -# # log.debug ("cipher : %s", pformat(cipher)) - -# # decrypted = cipher.decrypt(base64.b64decode(encodedEncrypted))[:16] -# # log.debug ("decrypted : %s", pformat(decrypted)) - -# # for i in range(1, len(base64.b64decode(encodedEncrypted))/16): - -# # cipher = AES.new(key, AES.MODE_CBC, base64.b64decode(encodedEncrypted)[(i-1)*16:i*16]) -# # log.debug ("cipher : %s", pformat(cipher)) - -# # decrypted += cipher.decrypt(base64.b64decode(encodedEncrypted)[i*16:])[:16] -# # log.debug ("decrypted : %s", pformat(decrypted)) - -# # log.debug ("decrypted.strip() : %s", pformat(decrypted.strip())) -# # return decrypted.strip() - - -# # cf : https://chase-seibert.github.io/blog/2016/01/29/cryptojs-pycrypto-ios-aes256.html - - - -# def encrypt(key, iv, plaintext): -# aes = AES.new(key, MODE, iv, segment_size=SEGMENT_SIZE) -# plaintext = _pad_string(plaintext) -# encrypted_text = aes.encrypt(plaintext) -# return binascii.b2a_hex(encrypted_text).rstrip() - -# def decrypt(key, iv, encrypted_text): -# aes = AES.new(key, MODE, iv, segment_size=SEGMENT_SIZE) -# encrypted_text_bytes = binascii.a2b_hex(encrypted_text) -# decrypted_text = aes.decrypt(encrypted_text_bytes) -# decrypted_text = _unpad_string(decrypted_text) -# return decrypted_text - -# def _pad_string(value): -# length = len(value) -# pad_size = BLOCK_SIZE - (length % BLOCK_SIZE) -# return value.ljust(length + pad_size, '\x00') - -# def _unpad_string(value): -# while value[-1] == '\x00': -# value = value[:-1] -# return value - -# # if __name__ == '__main__': -# # input_plaintext = 'The answer is no' -# # encrypted_text = encrypt(KEY, IV, input_plaintext) -# # decrypted_text = decrypt(KEY, IV, encrypted_text) -# # assert decrypted_text == input_plaintext - ### + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ### ### ROUTES @@ -152,22 +60,24 @@ def get(self): log.debug("anonymous_access_token_decoded : \n %s", pformat(anonymous_access_token_decoded) ) # salt_token = anonymous_access_token_decoded['jti'] # salt_token = salt_token.replace("-", "") - salt_token = public_key_str #.decode("utf-8") ### create corresponding refresh token - expires = app.config["JWT_ANONYMOUS_REFRESH_TOKEN_EXPIRES"] + expires = app.config["JWT_ANONYMOUS_REFRESH_TOKEN_EXPIRES"] anonymous_refresh_token = create_refresh_token(identity=anonymous_user, expires_delta=expires) log.debug("anonymous_access_token : \n %s", anonymous_access_token ) log.debug("anonymous_refresh_token : \n %s", anonymous_refresh_token ) - log.debug("salt_token : \n %s", salt_token ) ### store tokens in dict tokens = { 'access_token' : anonymous_access_token, 'refresh_token' : anonymous_refresh_token, - 'salt_token' : salt_token, + # 'salt_token' : salt_token, } + if app.config["SALT_MODE"]=="yes" : + salt_token = public_key_str #.decode("utf-8") + log.debug("salt_token : \n %s", salt_token ) + tokens["salt_token"] : salt_token return { "msg" : "anonymous user - an anonymous access_token has been created + a valid refresh_token for {} hours".format(expires) , diff --git a/auth_api/api/api_auth/endpoint_user_tokens.py b/auth_api/api/api_auth/endpoint_user_tokens.py index dce025e..a6ad1c3 100644 --- a/auth_api/api/api_auth/endpoint_user_tokens.py +++ b/auth_api/api/api_auth/endpoint_user_tokens.py @@ -142,15 +142,17 @@ def get(self) : log.debug("new_access_token : \n %s ", new_access_token) ### store tokens - token = { + tokens = { 'access_token' : new_access_token, - 'salt_token' : public_key_str, + # 'salt_token' : public_key_str, } + if app.config["SALT_MODE"]=="yes" : + tokens["salt_token"] : salt_token return { "msg" : "new access token for user : {} ".format(user_identity) , "data" : user_light, - "tokens" : token + "tokens" : tokens }, 200 ### indicates to redirect to other URL else : diff --git a/auth_api/api/api_users/endpoint_usr_register.py b/auth_api/api/api_users/endpoint_usr_register.py index 08a355a..2f7c8a1 100644 --- a/auth_api/api/api_users/endpoint_usr_register.py +++ b/auth_api/api/api_users/endpoint_usr_register.py @@ -124,9 +124,9 @@ def post(self): ### create user dict from form's data new_user_infos = { - "infos" : ns.payload, + "infos" : ns.payload, # "auth" : ns.payload - "log" : { "created_at" : datetime.utcnow() }, + "log" : { "created_at" : datetime.utcnow() }, "profile" : { "lang" : ns.payload["lang"]} } new_user = marshal( new_user_infos , model_user_complete_in ) @@ -166,9 +166,12 @@ def post(self): tokens = { 'access_token' : access_token, 'refresh_token' : refresh_token, - 'salt_token' : public_key_str, + # 'salt_token' : public_key_str, # 'access_token_confirm_email' : access_token_confirm_email } + if app.config["SALT_MODE"]=="yes" : + tokens["salt_token"] : public_key_str + log.info("tokens : \n %s", pformat(tokens)) ### update new user in db @@ -307,8 +310,10 @@ def get(self): tokens = { 'access_token' : access_token, 'refresh_token' : refresh_token, - 'salt_token' : public_key_str, + # 'salt_token' : public_key_str, } + if app.config["SALT_MODE"]=="yes" : + tokens["salt_token"] : public_key_str log.info("tokens : \n%s", pformat(tokens)) return { diff --git a/auth_api/config.py b/auth_api/config.py index f76b864..9c308db 100644 --- a/auth_api/config.py +++ b/auth_api/config.py @@ -55,11 +55,11 @@ class BaseConfig(object): SERVER_NAME_TEST = "True" """ MONGODB """ - MONGO_DBNAME = 'auth' - MONGO_URI = 'mongodb://localhost:27017/auth' + MONGO_DBNAME = 'auth' + MONGO_URI = 'mongodb://localhost:27017/auth' # collections - MONGO_COLL_USERS = "users" - MONGO_COLL_JWT_BLACKLIST = "jwt_blacklist" + MONGO_COLL_USERS = "users" + MONGO_COLL_JWT_BLACKLIST = "jwt_blacklist" """ EMAILING """ # email server diff --git a/auth_api/config_prod_example.py b/auth_api/config_prod_example.py index 569e9c4..705c8da 100644 --- a/auth_api/config_prod_example.py +++ b/auth_api/config_prod_example.py @@ -62,17 +62,6 @@ class BaseConfig(object): # collections MONGO_COLL_TAGS = "tags" MONGO_COLL_USERS = "users" - # MONGO_COLL_PROJECTS = "projects" - # MONGO_COLL_DATAMODELS_TEMPLATES = "datamodels_templates" - # MONGO_COLL_DATAMODELS_FIELDS = "datamodels_fields" - # MONGO_COLL_CONNECTORS = "connectors" - # MONGO_COLL_DATASETS_INPUTS = "datasets_inputs" - # MONGO_COLL_DATASETS_RAWS = "datasets_raws" - # MONGO_COLL_DATASETS_OUTPUTS = "datasets_outputs" - # MONGO_COLL_DATASETS_OUTPUTS_DOC = "datasets_outputs_docs" - # MONGO_COLL_RECIPES = "recipes" - # MONGO_COLL_CORR_DICTS = "corr_dicts" - # MONGO_COLL_LICENCES = "licences" MONGO_COLL_JWT_BLACKLIST = "jwt_blacklist" @@ -147,17 +136,17 @@ class Prod(DevEmail) : REDIRECTION_FRONT = "http://www.my-auth-frontend.com" """ HOST - real prod IP and domain name""" - DOMAIN_ROOT = "XXX.XX.XX.XXX" - DOMAIN_PORT = "4000" - SERVER_NAME = "XXX.XX.XX.XXX:4100" ### if True need to set SESSION_COOKIE_DOMAIN + cf : https://stackoverflow.com/questions/47666210/cookies-not-saved-in-the-browser - DOMAIN_NAME = "http://your-auth-instance.com" + DOMAIN_ROOT = "XXX.XX.XX.XXX" + DOMAIN_PORT = "4000" + SERVER_NAME = "XXX.XX.XX.XXX:4100" ### if True need to set SESSION_COOKIE_DOMAIN + cf : https://stackoverflow.com/questions/47666210/cookies-not-saved-in-the-browser + DOMAIN_NAME = "http://your-auth-instance.com" SERVER_NAME_TEST = "True" """ MONGODB """ MONGO_DBNAME = 'auth' MONGO_USER = "mongo_admin_user" MONGO_PASS = "mongo_admin_user_password" - MONGO_URI = 'mongodb://mongo_admin_user_password:mongo_admin_user@127.0.0.1:27017/auth' + MONGO_URI = 'mongodb://mongo_admin_user_password:mongo_admin_user@127.0.0.1:27017/auth' """ EMAILING """ @@ -166,10 +155,10 @@ class Prod(DevEmail) : MAIL_PORT = 465 MAIL_USE_TLS = False MAIL_USE_SSL = True - MAIL_USERNAME = "your.auth-instance.email-contact@my_email.com" # os.environ.get('MAIL_USERNAME') - MAIL_PASSWORD = "email_password_here" # os.environ.get('MAIL_PASSWORD') + MAIL_USERNAME = "your.auth-instance.email-contact@my_email.com" # os.environ.get('MAIL_USERNAME') + MAIL_PASSWORD = "email_password_here" # os.environ.get('MAIL_PASSWORD') # administrator list - ADMINS = ['your.app.email@my_email.com'] + ADMINS = ['your.app.email@my_email.com'] MAIL_DEFAULT_SENDER = 'your.app.email@my_email.com' """ ENCRYPTION FOR CONFIRMATION EMAIL """ diff --git a/prod_snippets/solidata_prod_git.md b/prod_snippets/prod_git.md similarity index 100% rename from prod_snippets/solidata_prod_git.md rename to prod_snippets/prod_git.md diff --git a/prod_snippets/solidata_prod_mongo.md b/prod_snippets/prod_mongo.md similarity index 100% rename from prod_snippets/solidata_prod_mongo.md rename to prod_snippets/prod_mongo.md diff --git a/prod_snippets/solidata_prod_nginx.md b/prod_snippets/prod_nginx.md similarity index 100% rename from prod_snippets/solidata_prod_nginx.md rename to prod_snippets/prod_nginx.md diff --git a/prod_snippets/solidata_back_supervisor.md b/prod_snippets/prod_supervisor.md similarity index 100% rename from prod_snippets/solidata_back_supervisor.md rename to prod_snippets/prod_supervisor.md diff --git a/prod_snippets/solidata_prod_ubuntu.md b/prod_snippets/prod_ubuntu.md similarity index 100% rename from prod_snippets/solidata_prod_ubuntu.md rename to prod_snippets/prod_ubuntu.md diff --git a/screenshots/endpoints_dataset_inputs.png b/screenshots/endpoints_dataset_inputs.png deleted file mode 100644 index 4fd72cc2cf218493debe6f3c82d2cc1f737a2b9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66358 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 z 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 T9rQfO?=Gj0n;#<_b-wXG$Cvky diff --git a/screenshots/endpoints_projects.png b/screenshots/endpoints_projects.png deleted file mode 100644 index d1c5b5c0644c59990bdbc3ceb571f56d73bad8df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 169981 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

    %LXn>SYGn$D_%6(&Y8zp523`HtC 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 %*(&LGFFVgq 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∋%o%O@lJ0ZVqWbale5 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%0DhQ`Fj2 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 diff --git a/wsgi.py b/wsgi.py index 32cb144..992ddb3 100644 --- a/wsgi.py +++ b/wsgi.py @@ -10,11 +10,11 @@ from auth_api.application import create_app -app = create_app( app_name='SOLIDATA_API', run_mode="prod" ) +app = create_app( app_name='AUTH_API', run_mode="prod" ) if __name__ == "main" : - log.debug("\n--- STARTING SOLIDATA API (PROD) ---\n") + log.debug("\n--- STARTING AUTH API (PROD) ---\n") ### initiate socketio socketio = SocketIO(app) diff --git a/wsgi_preprod.py b/wsgi_preprod.py index dc0504c..dc62b74 100644 --- a/wsgi_preprod.py +++ b/wsgi_preprod.py @@ -10,11 +10,11 @@ from auth_api.application import create_app -app = create_app( app_name='SOLIDATA_API', run_mode="preprod" ) +app = create_app( app_name='AUTH_API', run_mode="preprod" ) if __name__ == "main" : - log.debug("\n--- STARTING SOLIDATA API (PREPROD) ---\n") + log.debug("\n--- STARTING AUTH API (PREPROD) ---\n") ### initiate socketio socketio = SocketIO(app)