def update_visit(visit_id): try: current_user = get_user_if_exists() update_data = dict(request.get_json()) visit = VisitModel.query.filter_by(id_visit=visit_id).first() if current_user.id_user != visit.id_role: return ("unauthorized"), 403 try: # Delete selected existing media id_media_to_delete = json.loads(update_data.get("delete_media")) if len(id_media_to_delete): db.session.query(MediaOnVisitModel).filter( MediaOnVisitModel.id_media.in_(tuple(id_media_to_delete)), MediaOnVisitModel.id_data_source == visit_id, ).delete(synchronize_session="fetch") db.session.query(MediaModel).filter( MediaModel.id_media.in_(tuple(id_media_to_delete)) ).delete(synchronize_session="fetch") except Exception as e: current_app.logger.warning("[update_visit] delete media ", e) raise GeonatureApiError(e) visit.date = update_data.get("date") visit.json_data = update_data.get("data") db.session.commit() return ("Visit updated successfully"), 200 except Exception as e: current_app.logger.critical("[update_visit] Error: %s", str(e)) return {"message": str(e)}, 400
def update_observation(): try: update_data = request.form update_obs = {} for prop in ["cd_nom", "count", "comment", "date"]: update_obs[prop] = update_data[prop] try: _coordinates = json.loads(update_data["geometry"]) _point = Point(_coordinates["x"], _coordinates["y"]) _shape = asShape(_point) update_obs["geom"] = from_shape(Point(_shape), srid=4326) update_obs["municipality"] = get_municipality_id_from_wkb( update_obs['geom']) except Exception as e: current_app.logger.warning("[post_observation] coords ", e) raise GeonatureApiError(e) ObservationModel.query.filter_by( id_observation=update_data.get('id_observation')).update( update_obs, synchronize_session='fetch') db.session.commit() return ('observation updated successfully'), 200 except Exception as e: current_app.logger.critical("[post_observation] Error: %s", str(e)) return {"message": str(e)}, 400
def delete_user(): """list all logged users --- tags: - Authentication summary: Delete current logged user consumes: - application/json produces: - application/json responses: 200: description: Delete current logged user """ # Get logged user current_app.logger.debug("[delete_user] Delete current user") current_user = get_jwt_identity() if current_user: current_app.logger.debug( "[delete_user] current user is {}".format(current_user) ) user = UserModel.query.filter_by(username=current_user) # get username username = user.one().username # delete user try: db.session.query(UserModel).filter( UserModel.username == current_user ).delete() db.session.commit() current_app.logger.debug( "[delete_user] user {} succesfully deleted".format(username) ) except Exception as e: db.session.rollback() raise GeonatureApiError(e) return {"message": str(e)}, 400 return ( { "message": """Account "{}" have been successfully deleted""".format( username ) }, 200, )
def update_site(): try: current_user = get_jwt_identity() update_data = dict(request.get_json()) update_site = {} for prop in ["name", "id_type"]: update_site[prop] = update_data[prop] try: shape = asShape(update_data["geometry"]) update_site["geom"] = from_shape(Point(shape), srid=4326) except Exception as e: current_app.logger.warning("[update_site] coords ", e) raise GeonatureApiError(e) site = SiteModel.query.filter_by(id_site=update_data.get("id_site")) if current_user != UserModel.query.get(site.first().id_role).email: return ("unauthorized"), 403 site.update(update_site, synchronize_session="fetch") db.session.commit() return ("site updated successfully"), 200 except Exception as e: current_app.logger.critical("[update_site] Error: %s", str(e)) return {"message": str(e)}, 400
def post_site(): """Ajout d'un site Post a site --- tags: - Sites (External module) summary: Creates a new site consumes: - application/json produces: - application/json parameters: - name: body in: body description: JSON parameters. required: true schema: id: Site properties: id_program: type: integer description: Program foreign key required: true example: 1 name: type: string description: Site name default: none example: "Site 1" id_type: type: integer description: must be one of the supported site types' id required: True example: 1 geometry: type: string example: {"type":"Point", "coordinates":[5,45]} responses: 200: description: Site created """ try: request_data = dict(request.get_json()) datas2db = {} for field in request_data: if hasattr(SiteModel, field): datas2db[field] = request_data[field] current_app.logger.debug("datas2db: %s", datas2db) try: newsite = SiteModel(**datas2db) except Exception as e: current_app.logger.debug(e) raise GeonatureApiError(e) try: shape = asShape(request_data["geometry"]) newsite.geom = from_shape(Point(shape), srid=4326) except Exception as e: current_app.logger.debug(e) raise GeonatureApiError(e) id_role = get_id_role_if_exists() if id_role is not None: newsite.id_role = id_role role = UserModel.query.get(id_role) newsite.obs_txt = role.username newsite.email = role.email else: if newsite.obs_txt is None or len(newsite.obs_txt) == 0: newsite.obs_txt = "Anonyme" newsite.uuid_sinp = uuid.uuid4() db.session.add(newsite) db.session.commit() # Réponse en retour result = SiteModel.query.get(newsite.id_site) return { "message": "New site created.", "features": [format_site(result)] }, 200 except Exception as e: current_app.logger.warning("Error: %s", str(e)) return {"error_message": str(e)}, 400
def update_observation(): try: update_data = request.form update_obs = {} for prop in ["cd_nom", "count", "comment", "date"]: update_obs[prop] = update_data[prop] try: _coordinates = json.loads(update_data["geometry"]) _point = Point(_coordinates["x"], _coordinates["y"]) _shape = asShape(_point) update_obs["geom"] = from_shape(Point(_shape), srid=4326) update_obs["municipality"] = get_municipality_id_from_wkb( update_obs["geom"]) except Exception as e: current_app.logger.warning("[post_observation] coords ", e) raise GeonatureApiError(e) try: json_data = update_data.get("json_data") if json_data is not None: update_obs["json_data"] = json.loads(json_data) except Exception as e: current_app.logger.warning("[update_observation] json_data ", e) raise GeonatureApiError(e) ObservationModel.query.filter_by( id_observation=update_data.get("id_observation")).update( update_obs, synchronize_session="fetch") try: # Delete selected existing media id_media_to_delete = json.loads(update_data.get("delete_media")) if len(id_media_to_delete): db.session.query(ObservationMediaModel).filter( ObservationMediaModel.id_media.in_( tuple(id_media_to_delete)), ObservationMediaModel.id_data_source == update_data.get( "id_observation"), ).delete(synchronize_session="fetch") db.session.query(MediaModel).filter( MediaModel.id_media.in_(tuple(id_media_to_delete))).delete( synchronize_session="fetch") except Exception as e: current_app.logger.warning("[update_observation] delete media ", e) raise GeonatureApiError(e) try: file = save_upload_files( request.files, "obstax", update_data.get("cd_nom"), update_data.get("id_observation"), ObservationMediaModel, ) current_app.logger.debug( "[post_observation] ObsTax UPLOAD FILE {}".format(file)) except Exception as e: current_app.logger.warning( "[post_observation] ObsTax ERROR ON FILE SAVING", str(e)) # raise GeonatureApiError(e) db.session.commit() return ("observation updated successfully"), 200 except Exception as e: current_app.logger.critical("[post_observation] Error: %s", str(e)) return {"message": str(e)}, 400
def post_observation(): """Post a observation add a observation to database --- tags: - observations # security: # - bearerAuth: [] summary: Creates a new observation (JWT auth optional, if used, obs_txt replaced by username) consumes: - application/json - multipart/form-data produces: - application/json parameters: - name: json in: body description: JSON parameters. required: true schema: id: observation required: - cd_nom - date - geom properties: id_program: type: string description: Program unique id example: 1 default: 1 cd_nom: type: string description: CD_Nom Taxref example: 3582 obs_txt: type: string default: none description: User name required: false example: Martin Dupont count: type: integer description: Number of individuals default: none example: 1 date: type: string description: Date required: false example: "2018-09-20" geometry: type: string description: Geometry (GeoJson format) example: {"type":"Point", "coordinates":[5,45]} responses: 200: description: Adding a observation """ try: request_datas = request.form current_app.logger.debug("[post_observation] request data:", request_datas) datas2db = {} for field in request_datas: if hasattr(ObservationModel, field): datas2db[field] = request_datas[field] current_app.logger.debug("[post_observation] datas2db: %s", datas2db) try: newobs = ObservationModel(**datas2db) except Exception as e: current_app.logger.warning("[post_observation] data2db ", e) raise GeonatureApiError(e) try: _coordinates = json.loads(request_datas["geometry"]) _point = Point(_coordinates["x"], _coordinates["y"]) _shape = asShape(_point) newobs.geom = from_shape(Point(_shape), srid=4326) except Exception as e: current_app.logger.warning("[post_observation] coords ", e) raise GeonatureApiError(e) try: json_data = request_datas.get("json_data") if json_data is not None: newobs.json_data = json.loads(json_data) except Exception as e: current_app.logger.warning("[post_observation] json_data ", e) raise GeonatureApiError(e) id_role = get_id_role_if_exists() if id_role: newobs.id_role = id_role role = UserModel.query.get(id_role) newobs.obs_txt = role.username newobs.email = role.email else: if newobs.obs_txt is None or len(newobs.obs_txt) == 0: newobs.obs_txt = "Anonyme" newobs.municipality = get_municipality_id_from_wkb(newobs.geom) newobs.uuid_sinp = uuid.uuid4() db.session.add(newobs) db.session.commit() current_app.logger.debug(newobs.as_dict()) # Réponse en retour features = generate_observation_geojson(newobs.id_observation) current_app.logger.debug("FEATURES: {}".format(features)) # Enregistrement de la photo et correspondance Obs Photo try: file = save_upload_files( request.files, "obstax", datas2db["cd_nom"], newobs.id_observation, ObservationMediaModel, ) current_app.logger.debug( "[post_observation] ObsTax UPLOAD FILE {}".format(file)) features[0]["properties"]["images"] = file except Exception as e: current_app.logger.warning( "[post_observation] ObsTax ERROR ON FILE SAVING", str(e)) # raise GeonatureApiError(e) return ({ "message": "Nouvelle observation créée.", "features": features }, 200) except Exception as e: current_app.logger.critical("[post_observation] Error: %s", str(e)) return {"message": str(e)}, 400
def post_program(): """Post a program add a program to database --- tags: - Programs summary: Creates a new program (JWT auth required) consumes: - application/json produces: - application/json parameters: - name: body in: body description: JSON parameters. required: true schema: id: Program required: - title - short_desc - long_desc - module properties: title: type: string description: Titre example: Mon premier programme short_desc: type: string default: none description: Description courte (< 200 caractères) required: true example: Premier programme de GeoNature-citizen long_desc: type: string description: Description longue et formatée (html) default: none example: "<h1> Long Description</h1> <p>jkll kjlk jlkj lkj lkjl j</p>" module: type: integer description: module associé (observations par défaut) required: true example: 1 default: 1 geometry: type: string description: Geometry (GeoJson format) example: {"type":"MultiPolygon","coordinates":[[[[4.95011308535733,45.0390394629218],[4.95012774926563,45.0449295197412],[4.95213300654567,45.0470559724217],[4.94818959208552,45.0498360160783],[4.94959107838521,45.0528647341048],[4.94613379711984,45.0524658617567],[4.94223384716856,45.0557853235726],[4.94070251187581,45.0684212799123],[4.93356436550241,45.0696622178299],[4.93751735253846,45.0814102522522],[4.9356315885774,45.087531523579],[4.93717248590092,45.0934761737063],[4.94681411006441,45.1001442744088],[4.95281174113414,45.1091091591692],[4.95869542090154,45.1056914521367],[4.96065478071604,45.1082509603287],[4.97080808349588,45.1076305993364],[4.98480525693456,45.102437520157],[4.99341347580405,45.1031035389658],[4.99808759644944,45.1054246923432],[5.00092421908124,45.1047253177017],[5.0045486107792,45.1008142602692],[5.00709088715848,45.104677507704],[5.0180379798632,45.1119826548125],[5.03104379372745,45.1156465107392],[5.03661054672007,45.1155089388635],[5.04537021415107,45.1244096813295],[5.04706655059779,45.1238291235659],[5.05584574495711,45.1279910207948],[5.06336763678235,45.1283925305999],[5.06869622533834,45.1310680128585],[5.07365419172495,45.1388301868816],[5.07999876794354,45.1427743015072],[5.07786342433626,45.1459305887331],[5.07055416483018,45.1465258596015],[5.06964232152214,45.1493980570617],[5.06025867953794,45.1569215891027],[5.05547971596628,45.1585139252094],[5.05176873268989,45.1552225588093],[5.04756695617908,45.1565877672145],[5.04431724602707,45.1644925692554],[5.04089085192047,45.1661945845073],[5.04386532899611,45.1810199745064],[5.04933936274465,45.1823427467976],[5.05102620061224,45.1842302996503],[5.05563122978815,45.1820018787664],[5.06485456906333,45.1820658362641],[5.06833004883646,45.1868383888935],[5.07379945760164,45.1893760533553],[5.07569119937242,45.1957180602901],[5.05802940191996,45.2049081418594],[5.05675626359527,45.2090839465506],[5.04743286723077,45.2123177236168],[5.04249503389214,45.2170198395818],[5.04506160540422,45.2175043052525],[5.04835150577254,45.2224160324905],[5.05038242155581,45.2291252278791],[5.05530600320449,45.230944306372],[5.05710468076905,45.2340907850544],[5.06914961548774,45.2367867546052],[5.07466099643677,45.2362071659723],[5.08298237168288,45.2289455127812],[5.08794182999759,45.2180710885453],[5.09294038769495,45.2198420705493],[5.09336579920924,45.2237072821965],[5.10117831453134,45.2270735050436],[5.10176092806738,45.2340793455594],[5.10880292723782,45.2385945130566],[5.10895424532246,45.2405733037282],[5.11964567240535,45.2431092934839],[5.12297225619446,45.2460906914165],[5.12760879707125,45.2469663223909],[5.13144806545964,45.2433261677798],[5.13660795731605,45.2445517427852],[5.14136787363286,45.242992395456],[5.1416388251409,45.247391916997],[5.14479725407106,45.2479528698042],[5.15310224581174,45.256305395347],[5.1558790822872,45.2545674373686],[5.16043429191985,45.2549568862231],[5.15660987500625,45.2510403530431],[5.15668551088512,45.247390795469],[5.16102270585508,45.2461179988123],[5.17654087698441,45.2484020449113],[5.18278996227186,45.2415784169858],[5.18457623195412,45.2311936470833],[5.19014655239323,45.226634775023],[5.19083374182881,45.2240090639432],[5.20020765687963,45.2202667700037],[5.20171318967148,45.2173996682677],[5.18333302980776,45.2176703892727],[5.17786114585021,45.216579197969],[5.16741518360163,45.2101347721251],[5.16830338931039,45.208397077383],[5.16472478267799,45.2005668463021],[5.16656871850906,45.2004770379442],[5.16422191440303,45.1977842451736],[5.16876107747624,45.1985338759003],[5.17548555169683,45.1808202387956],[5.18961377581572,45.1705185182698],[5.18715196717163,45.1671619236075],[5.19025705826227,45.1628944790427],[5.19170053071256,45.1545791620435],[5.18979927498971,45.1521934598712],[5.18124320717912,45.1488931706186],[5.18767141108609,45.1453174089338],[5.18808752188842,45.1419674511635],[5.19100031469761,45.1399736537568],[5.18653992236592,45.1349449088754],[5.18849497110581,45.1267007205165],[5.18743813082219,45.1208305558507],[5.18314983283291,45.1175548137929],[5.17286179586614,45.1035871134681],[5.16289429760852,45.0984305870661],[5.15781190291416,45.0893236009275],[5.15833063773881,45.0843144937],[5.15487314397137,45.0797156282626],[5.14484841481812,45.081530357532],[5.14097807452814,45.0764076084662],[5.13759836680931,45.0814444957027],[5.13454304219611,45.0746755900072],[5.13902828936142,45.0726259924146],[5.14856095639905,45.0769011542207],[5.14889777213862,45.0744176610734],[5.15679047477638,45.0658073178223],[5.16264058734893,45.0655677952186],[5.17031694666971,45.0681747376366],[5.17300029929547,45.0763911578227],[5.17938465768597,45.0833102200943],[5.18333653512374,45.084881210161],[5.19355577399695,45.0835005397074],[5.20820566986281,45.0842200206837],[5.22612330271311,45.0791795962095],[5.22749441889871,45.0772155771411],[5.22565665899745,45.0735231959789],[5.23562639774014,45.0669282376067],[5.23715721052478,45.0518099333837],[5.23030540448993,45.0367608064811],[5.23058306799345,45.0281081209971],[5.2220780309375,45.001039993189],[5.22691639569865,45.0001145884815],[5.226894042366,44.9934856486068],[5.22364374509023,44.9851558662931],[5.20892376489755,44.9710646253918],[5.20667934881251,44.960147451182],[5.19453778776847,44.940364978686],[5.18683779361078,44.920151871963],[5.17944855684884,44.9166042035759],[5.1686834319402,44.9194809042976],[5.16013674430449,44.9184314608507],[5.15003495696524,44.9111967376626],[5.14593160249067,44.9049893081196],[5.14857417905612,44.9005248830011],[5.15204094776685,44.8987284581497],[5.15094553083893,44.8946155497301],[5.14271798648966,44.8905323965831],[5.13325022964874,44.8911199703582],[5.13591001472426,44.8887631195134],[5.14579970675824,44.8902747447576],[5.16124573794876,44.8873362184647],[5.15360596742221,44.878423819644],[5.1504402779308,44.8701899623236],[5.14565569893684,44.8666258132252],[5.14577328061453,44.8567792193995],[5.14083358996452,44.8431304637043],[5.13707376047591,44.8388077136138],[5.1352458611125,44.8310161811302],[5.10513972510039,44.8260705758419],[5.10214664970183,44.826577658668],[5.09800310139488,44.8301686187737],[5.08882444372737,44.8314586185258],[5.07846636684274,44.8303021988801],[5.07346574954468,44.8316386554624],[5.07582609900681,44.8037198468329],[5.0704281404497,44.7924908655173],[5.0506124160193,44.7932824447922],[5.04125255381155,44.7984986340404],[5.01734776475004,44.8066634046818],[5.01305029927326,44.8095964458749],[5.01166256121674,44.7902674921801],[5.0069214262491,44.7888944381386],[5.00037206477324,44.7811235228854],[4.99257590289959,44.784857337902],[4.98429856553397,44.7792870169617],[4.97462229748805,44.7777576960561],[4.96956039040425,44.779081570672],[4.95976011934109,44.7761572505552],[4.95278955009484,44.7716782848881],[4.94631833497131,44.7779431125554],[4.95566407508391,44.7892611347139],[4.96095326950928,44.7929682109336],[4.95242253961387,44.8058981966876],[4.95460663924081,44.8094080746354],[4.95401895756149,44.8132459730087],[4.95240785486136,44.8113020365225],[4.94824196686328,44.8155810847149],[4.94202812446175,44.8181036578891],[4.93321078969455,44.8185278648161],[4.92364488975878,44.8148306390719],[4.92285438566429,44.8157629490509],[4.9024651541033,44.811476538669],[4.89670073253759,44.8011195283103],[4.89294276236153,44.8037143697859],[4.89007912589346,44.803195851475],[4.88370083246239,44.8091491283895],[4.88384786984447,44.8108937527577],[4.87799089353244,44.8112902751527],[4.87274253671441,44.8143869460894],[4.86811006703501,44.8211833676286],[4.86194928075535,44.8254296018837],[4.85625664571251,44.8090174984433],[4.85097635618403,44.8096370884021],[4.85064947248167,44.8066256381345],[4.83284927882366,44.8131801789493],[4.82723507781334,44.810553111044],[4.8223503792233,44.810120160829],[4.81910687191008,44.8115332566877],[4.80098960119933,44.8059843251289],[4.79907426304527,44.8109594623482],[4.79984692586181,44.8129641726745],[4.80448725265381,44.8124835223006],[4.81057623206212,44.8161306185757],[4.8135905522056,44.8154419744158],[4.82251308092393,44.817087844678],[4.81991312062405,44.8333046953117],[4.82085299030274,44.8377020631303],[4.82627691437617,44.8402425919144],[4.84001360808841,44.8418798499918],[4.84437716331824,44.846013107264],[4.84476658440316,44.8582545261278],[4.8612470587789,44.8749014638387],[4.86061816353658,44.8807658518417],[4.8547342299931,44.8897711463414],[4.85509992795196,44.9000678478834],[4.86883063304508,44.9098073471605],[4.87379338011717,44.9221701316786],[4.88658929984345,44.9366516305336],[4.87568416232782,44.9552087321462],[4.86017017535819,44.9658624557115],[4.85317038876744,44.9786149568729],[4.85543452566304,44.9783970889983],[4.85862258135809,44.9830811209621],[4.86447944606759,44.9863334227971],[4.87308523978914,44.9977619019761],[4.88255745792513,44.998601744656],[4.88719263583906,45.0058183489746],[4.90540164251165,45.0070481574135],[4.90954698285881,45.0146865895326],[4.91267301018215,45.0162450643106],[4.92669858969933,45.0134993657835],[4.9391772821066,45.0174526564036],[4.94593688838917,45.023783362203],[4.93478848225878,45.0267787114297],[4.93222920887492,45.032109985756],[4.93621846444971,45.0350758833101],[4.95011308535733,45.0390394629218]]]]} responses: 200: description: Adding a program """ try: request_datas = dict(request.get_json()) # if request.files: # file = request.files['file'] # file.save() # else: # file = None datas2db = {} for field in request_datas: if hasattr(ProgramsModel, field): datas2db[field] = request_datas[field] try: newprogram = ProgramsModel(**datas2db) except Exception as e: raise GeonatureApiError(e) try: shape = asShape(request_datas["geometry"]) newprogram.geom = from_shape(MultiPolygon(shape), srid=4326) except Exception as e: raise GeonatureApiError(e) db.session.add(newprogram) db.session.commit() # Réponse en retour return ( { "message": "Nouveau programme créé.", "features": newprogram.as_dict() }, 200, ) except Exception as e: current_app.logger.critical("[post_program] error : %s", str(e)) return {"message": str(e)}, 400
def save_uploaded_files( # pylint: disable=too-many-locals request_file, prefix="none", cdnom="0", id_data_source=None, matching_model=None, ): """Save files on server and filenames in db from POST request for each files in flask request.files, this function does: * verify if file type is in allowed media * generate a filename from ``prefix``, ``cdnom``, ``index``, ``timestamp`` * save file in ``./media`` dir * save filename in MediaModel and then in a matching media model :param request_file: request files from post request. :type request_file: function :param prefix: filename prefix :type prefix: str :param cdnom: species id from taxref cdnom :type cdnom: int :param id_data_source: source id in matching model :type id_data_source: int :param matching_model: matching model of observation (eg: ``ObservationMediaModel`` or ``SiteMediaModel``) :type matching_model: class :returns: a filename list :rtype: list """ # noqa: E501 files = [] try: i = 0 for file in request_file.getlist("files"): i = i + 1 filename = file.filename current_app.logger.debug( "[save_uploaded_files] %s is an allowed filename : %s", filename, allowed_extension(filename), ) if allowed_extension(filename): # save file current_app.logger.debug( '[save_uploaded_files] Preparing file "%s" saving', filename, ) ext = filename.rsplit(".", 1)[1].lower() timestamp = now().strftime("%Y%m%d_%H%M%S") filename = f"{prefix}_{str(cdnom)}_{i}_{timestamp}.{ext}" current_app.logger.debug( "[save_uploaded_files] new filename : %s", filename) file.save(os.path.join(str(MEDIA_DIR), filename)) # Save media filename to Database try: newmedia = MediaModel(filename=filename) current_app.logger.debug( "[save_uploaded_files] newmedia %s", newmedia) db.session.add(newmedia) db.session.commit() id_media = newmedia.id_media current_app.logger.debug( "[save_uploaded_files] id_media : %s", str(id_media)) # return id_media except Exception as e: current_app.logger.debug( "[save_uploaded_files] ERROR MEDIAMODEL: %s", e) raise GeonatureApiError(e) # Save id_media in matching table try: newmatch = matching_model(id_media=id_media, id_data_source=id_data_source) db.session.add(newmatch) db.session.commit() id_match = newmatch.id_match current_app.logger.debug( "[save_uploaded_files] id_match %s", id_match) except Exception as e: current_app.logger.debug( "[save_uploaded_files] ERROR MATCH MEDIA: %s", e) raise GeonatureApiError(e) current_app.logger.debug( "[save_uploaded_files] Fichier %s enregistré", filename) files.append(filename) except Exception as e: current_app.logger.debug( "[save_uploaded_files] ERROR save_upload_file : %s", e) raise GeonatureApiError(e) return files
def registration(): """ User registration --- tags: - Authentication summary: Creates a new observation consumes: - application/json produces: - application/json parameters: - name: body in: body description: JSON parameters required: true schema: required: - name - surname - username - email - password properties: name: type: string surname: type: string username: type: string example: user1 email: type: string password: type: string example: user1 responses: 200: description: user created """ try: request_datas = dict(request.get_json()) datas_to_save = {} for data in request_datas: if hasattr(UserModel, data) and data != "password": datas_to_save[data] = request_datas[data] # Hashed password datas_to_save["password"] = UserModel.generate_hash(request_datas["password"]) # Protection against admin creation from API datas_to_save["admin"] = False if "extention" in request_datas and "avatar" in request_datas: extention = request_datas["extention"] imgdata = base64.b64decode( request_datas["avatar"].replace( "data:image/" + extention + ";base64,", "" ) ) filename = "avatar_" + request_datas["username"] + "." + extention datas_to_save["avatar"] = filename try: newuser = UserModel(**datas_to_save) except Exception as e: db.session.rollback() current_app.logger.critical(e) # raise GeonatureApiError(e) return ({"message": "La syntaxe de la requête est erronée."}, 400) try: newuser.save_to_db() except IntegrityError as e: db.session.rollback() # error causality ? current_app.logger.critical("IntegrityError: %s", str(e)) if UserModel.find_by_username(newuser.username): return ( { "message": """L'utilisateur "{}" existe déjà.""".format( newuser.username ) }, 400, ) elif ( db.session.query(UserModel) .filter(UserModel.email == newuser.email) .one() ): return ( { "message": """Un email correspondant est déjà enregistré.""".format( newuser.email ) }, 400, ) else: raise GeonatureApiError(e) access_token = create_access_token(identity=newuser.username) refresh_token = create_refresh_token(identity=newuser.username) # save user avatar if "extention" in request_datas and "avatar" in request_datas: handler = open(os.path.join(str(MEDIA_DIR), filename), "wb+") handler.write(imgdata) handler.close() # send confirm mail try: confirm_user_email(newuser) except Exception as e: return {"message mail faild": str(e)}, 500 return ( { "message": """Félicitations, l'utilisateur "{}" a été créé. \r\n Vous allez recevoir un email pour activer votre compte """.format( newuser.username ), "username": newuser.username, "access_token": access_token, "refresh_token": refresh_token, }, 200, ) except Exception as e: current_app.logger.critical("grab all: %s", str(e)) return {"message": str(e)}, 500
def registration(): """ User registration --- tags: - Authentication summary: Creates a new observation consumes: - application/json produces: - application/json parameters: - name: body in: body description: JSON parameters required: true schema: required: - name - surname - username - email - password properties: name: type: string surname: type: string username: type: string example: user1 email: type: string password: type: string example: user1 responses: 200: description: user created """ try: request_datas = dict(request.get_json()) if ("HCAPTCHA_SECRET_KEY" in current_app.config and current_app.config["HCAPTCHA_SECRET_KEY"] is not None): if (not "captchaToken" in request_datas or request_datas["captchaToken"] is None): return ( { "message": "Veuillez confirmer que vous êtes un humain." }, 400, ) params = { "response": request_datas["captchaToken"], "secret": current_app.config["HCAPTCHA_SECRET_KEY"], } response = requests.post("https://hcaptcha.com/siteverify", data=params) captchaResponse = response.json() if not captchaResponse["success"]: return ({"message": "Captcha non valide."}, 400) datas_to_save = {} for data in request_datas: if hasattr(UserModel, data) and data != "password": datas_to_save[data] = request_datas[data] # Hashed password datas_to_save["password"] = UserModel.generate_hash( request_datas["password"]) if current_app.config["CONFIRM_EMAIL"]["USE_CONFIRM_EMAIL"] == False: datas_to_save["active"] = True # Protection against admin creation from API datas_to_save["admin"] = False if "extention" in request_datas and "avatar" in request_datas: extention = request_datas["extention"] imgdata = base64.b64decode(request_datas["avatar"].replace( "data:image/" + extention + ";base64,", "")) filename = "avatar_" + request_datas["username"] + "." + extention datas_to_save["avatar"] = filename try: newuser = UserModel(**datas_to_save) except Exception as e: db.session.rollback() current_app.logger.critical(e) # raise GeonatureApiError(e) return ({"message": "La syntaxe de la requête est erronée."}, 400) try: newuser.save_to_db() except IntegrityError as e: db.session.rollback() # error causality ? current_app.logger.critical("IntegrityError: %s", str(e)) if UserModel.find_by_username(newuser.username): return ( { "message": """L'utilisateur "{}" existe déjà.""".format( newuser.username) }, 400, ) elif (db.session.query(UserModel).filter( UserModel.email == newuser.email).one()): return ( { "message": "Un email correspondant est déjà enregistré." }, 400, ) else: raise GeonatureApiError(e) access_token = create_access_token(identity=newuser.username) refresh_token = create_refresh_token(identity=newuser.username) # save user avatar if "extention" in request_datas and "avatar" in request_datas: handler = open(os.path.join(str(MEDIA_DIR), filename), "wb+") handler.write(imgdata) handler.close() try: if (current_app.config["CONFIRM_EMAIL"]["USE_CONFIRM_EMAIL"] is False): message = ( """Félicitations, l'utilisateur "{}" a été créé.""".format( newuser.username), ) confirm_user_email(newuser, with_confirm_link=False) else: message = ( """Félicitations, l'utilisateur "{}" a été créé. \r\n Vous allez recevoir un email pour activer votre compte """. format(newuser.username), ) confirm_user_email(newuser) except Exception as e: return {"message mail failed": str(e)}, 500 # send confirm mail return ( { "message": message, "username": newuser.username, "access_token": access_token, "refresh_token": refresh_token, }, 200, ) except Exception as e: current_app.logger.critical("grab all: %s", str(e)) return {"message": str(e)}, 500
def registration(): """ User registration --- tags: - Authentication summary: Creates a new observation consumes: - application/json produces: - application/json parameters: - name: body in: body description: JSON parameters required: true schema: required: - name - surname - username - email - password properties: name: type: string surname: type: string username: type: string example: user1 email: type: string password: type: string example: user1 responses: 200: description: user created """ try: request_datas = dict(request.get_json()) # Génération du dictionnaire des données à sauvegarder datas_to_save = {} for data in request_datas: if hasattr(UserModel, data) and data != "password": datas_to_save[data] = request_datas[data] # Hashed password datas_to_save["password"] = UserModel.generate_hash( request_datas["password"]) # Protection against admin creation from API datas_to_save["admin"] = False try: newuser = UserModel(**datas_to_save) except Exception as e: db.session.rollback() current_app.logger.critical(e) # raise GeonatureApiError(e) return ({"message": "La syntaxe de la requête est erronée."}, 400) try: newuser.save_to_db() except IntegrityError as e: db.session.rollback() # error causality ? current_app.logger.critical("IntegrityError: %s", str(e)) if UserModel.find_by_username(newuser.username): return ( { "message": """L'utilisateur "{}" existe déjà.""".format( newuser.username) }, 400, ) elif (db.session.query(UserModel).filter( UserModel.email == newuser.email).one()): return ( { "message": """Un email correspondant est déjà enregistré.""". format(newuser.email) }, 400, ) else: raise GeonatureApiError(e) access_token = create_access_token(identity=newuser.username) refresh_token = create_refresh_token(identity=newuser.username) return ( { "message": """Félicitations, l'utilisateur "{}" a été créé""".format( newuser.username), "username": newuser.username, "access_token": access_token, "refresh_token": refresh_token, }, 200, ) except Exception as e: current_app.logger.critical("grab all: %s", str(e)) return {"message": str(e)}, 500
def save_upload_files( request_file, prefix="none", cdnom="0", id_data_source=None, matching_model=None, ): """Save files on server and filenames in db from POST request for each files in flask request.files, this function does: * verify if file type is in allowed medias * generate a filename from ``prefix``, ``cdnom``, ``index``, ``timestamp`` * save file in ``./media`` dir * save filename in MediaModel and then in a matching media model :param request_file: request files from post request. :type request_file: function :param prefix: filename prefix :type prefix: str :param cdnom: species id from taxref cdnom :type cdnom: int :param id_data_source: source id in matching model :type id_data_source: int :param matching_model: matching model of observation (eg: ``ObservationMediaModel`` or ``SiteMediaModel``) :type matching_model: class :returns: a filename list :rtype: list """ files = [] try: i = 0 for file in request_file.getlist("file"): if isinstance(file, FileStorage): i = i + 1 filename = file.filename current_app.logger.debug( "[save_upload_files] {} is an allowed filename : {}". format(filename, allowed_file(filename))) if allowed_file(filename): # save file current_app.logger.debug( '[save_upload_files] Preparing file "{}" saving'. format(filename)) ext = filename.rsplit(".", 1)[1].lower() timestamp = datetime.datetime.utcnow().strftime( "%Y%m%d_%H%M%S") filename = "{}_{}_{}_{}.{}".format(prefix, str(cdnom), i, timestamp, ext) current_app.logger.debug( "[save_upload_files] new filename : {}".format( filename)) file.save(os.path.join(str(MEDIA_DIR), filename)) # Save media filename to Database try: newmedia = MediaModel(filename=filename) current_app.logger.debug( "[save_upload_files] newmedia {}".format(newmedia)) db.session.add(newmedia) db.session.commit() id_media = newmedia.id_media current_app.logger.debug( "[save_upload_files] id_media : ".format( str(id_media))) # return id_media except Exception as e: current_app.logger.debug( "[save_upload_files] ERROR MEDIAMODEL: {}".format( e)) raise GeonatureApiError(e) # Save id_media in matching table try: newmatch = matching_model( id_media=id_media, id_data_source=id_data_source) db.session.add(newmatch) db.session.commit() id_match = newmatch.id_match current_app.logger.debug( "[save_upload_files] id_match {}".format(id_match)) except Exception as e: current_app.logger.debug( "[save_upload_files] ERROR MATCH MEDIA: {}".format( e)) raise GeonatureApiError(e) # log current_app.logger.debug( "[save_upload_files] Fichier {} enregistré".format( filename)) files.append(filename) except Exception as e: current_app.logger.debug( "[save_upload_files] ERROR save_upload_file : {}".format(e)) raise GeonatureApiError(e) return files
def registration(): """ User registration --- tags: - Authentication summary: register user consumes: - application/json produces: - application/json parameters: - name: body in: body description: JSON parameters required: true schema: required: - name - surname - username - email - password properties: name: type: string surname: type: string username: type: string example: user1 email: type: string password: type: string example: user1 responses: 200: description: user created """ try: request_data = dict(request.get_json()) data_to_save = dict() for data in request_data: if hasattr(UserModel, data) and data != "password": data_to_save[data] = request_data[data] data_to_save["password"] = UserModel.generate_hash(request_data["password"]) data_to_save["admin"] = False try: newuser = UserModel(**data_to_save) except Exception as e: db.session.rollback() current_app.logger.critical(e) # raise GeonatureApiError(e) return ( {"message": "les informations d'enregistrement sont erronées."}, 400, ) try: newuser.save_to_db() except IntegrityError as e: db.session.rollback() # error causality ? current_app.logger.critical("IntegrityError: %s", str(e)) if UserModel.find_by_username(newuser.username): return ( { "message": f"""L'utilisateur "{newuser.username}" est déjà enregistré.""" # noqa: E501 }, 400, ) if ( db.session.query(UserModel) .filter(UserModel.email == newuser.email) .one() ): return ( {"message": "Un email correspondant est déjà enregistré."}, 400, ) raise GeonatureApiError(e) access_token = create_access_token(identity=newuser.username) refresh_token = create_refresh_token(identity=newuser.username) return ( { "message": """Félicitations, l'utilisateur "{}" a été créé""".format( newuser.username ), "username": newuser.username, "access_token": access_token, "refresh_token": refresh_token, }, 200, ) except Exception as e: current_app.logger.critical("grab all: %s", str(e)) return {"message": str(e)}, 500