From 1540b3e806f33f1dcf6232192ddf3d944a7e7315 Mon Sep 17 00:00:00 2001 From: KF7EEL Date: Thu, 22 Apr 2021 10:03:48 -0700 Subject: [PATCH] add app mode to API --- config.py | 3 ++ dev/json_templates.py | 17 ++++++++ full_bridge-SAMPLE.cfg | 3 ++ full_bridge.py | 23 ++++++++-- scripts/dashboard/dashboard.py | 76 +++++++++++++++++++++++++--------- 5 files changed, 98 insertions(+), 24 deletions(-) diff --git a/config.py b/config.py index c07721c..0696786 100755 --- a/config.py +++ b/config.py @@ -170,6 +170,9 @@ def build_config(_config_file): 'MAILBOX_FILE': config.get(section, 'MAILBOX_FILE'), 'EMERGENCY_SOS_FILE': config.get(section, 'EMERGENCY_SOS_FILE'), 'USER_SETTINGS_FILE': config.get(section, 'USER_SETTINGS_FILE'), + 'USE_API': config.getboolean(section, 'USE_API'), + 'AUTHORIZED_TOKENS_FILE': config.get(section, 'AUTHORIZED_TOKENS_FILE'), + }) if not CONFIG['LOGGER']['LOG_FILE']: diff --git a/dev/json_templates.py b/dev/json_templates.py index 742aab5..8fc838b 100644 --- a/dev/json_templates.py +++ b/dev/json_templates.py @@ -79,3 +79,20 @@ app_response = { json_object = json.dumps(app_response, indent = 4) print(json_object) + +msg_xfer = { + 'mode':'raw', + 'system_name':'ABC', + 'response_url':'http://localhost:8093/api/', + 'auth_type':'private', + 'credentials': { + 'user':'test_name', + 'password':'passw0rd', + }, + 'data':{ + 1:{'MMDVM Packet 1'}, + 2:{'MMDVM Packet 2'} + + } + +} diff --git a/full_bridge-SAMPLE.cfg b/full_bridge-SAMPLE.cfg index 6f6c82d..f6662ac 100644 --- a/full_bridge-SAMPLE.cfg +++ b/full_bridge-SAMPLE.cfg @@ -168,8 +168,11 @@ EMERGENCY_SOS_FILE: /tmp/gps_data_user_sos.txt # User settings file, MUST configure using absolute path. USER_SETTINGS_FILE: /path/to/user_settings.txt +# API settings # Authorized Apps file - data used for the dashboard API +USE_API: True AUTHORIZED_APPS_FILE: /path/to/authorized_apps.py +AUTHORIZED_TOKENS_FILE: /tmp/hblink_auth_tokens.txt # The following options are used for the dashboard. The dashboard is optional. # Title of the Dashboard diff --git a/full_bridge.py b/full_bridge.py index a843e33..fc442e9 100644 --- a/full_bridge.py +++ b/full_bridge.py @@ -2164,6 +2164,11 @@ if __name__ == '__main__': emergency_sos_file = CONFIG['GPS_DATA']['EMERGENCY_SOS_FILE'] # User APRS settings user_settings_file = CONFIG['GPS_DATA']['USER_SETTINGS_FILE'] + + #API variables + auth_token_file = CONFIG['GPS_DATA']['AUTHORIZED_TOKENS_FILE'] + use_api = CONFIG['GPS_DATA']['USE_API'] + # Check if user_settings (for APRS settings of users) exists. Creat it if not. if Path(user_settings_file).is_file(): pass @@ -2187,13 +2192,23 @@ if __name__ == '__main__': with open(bb_file, 'w') as user_bb_file: user_bb_file.write("[]") user_bb_file.close() + #Only create if API enabled + if use_api == True: + if Path(auth_token_file).is_file(): + pass + else: + Path(auth_token_file).touch() + with open(auth_token_file, 'w') as auth_token: + auth_token.write("[]") + auth_token.close() + if Path(the_mailbox_file).is_file(): pass else: Path(the_mailbox_file).touch() - with open(the_mailbox_file, 'w') as user_loc_file: - user_loc_file.write("[]") - user_loc_file.close() + with open(the_mailbox_file, 'w') as mailbox_file: + mailbox_file.write("[]") + mailbox_file.close() try: Path('/tmp/.hblink_data_que/').mkdir(parents=True, exist_ok=True) except: @@ -2274,7 +2289,7 @@ if __name__ == '__main__': # Check for outgoing SMS data_que_check() # APRS beacon and receive - if aprs_callsign == 'N0CALL': + if 'N0CALL' in aprs_callsign: logger.info('APRS callsighn set to N0CALL, packet not sent.') pass else: diff --git a/scripts/dashboard/dashboard.py b/scripts/dashboard/dashboard.py index 87f8955..d29e21c 100644 --- a/scripts/dashboard/dashboard.py +++ b/scripts/dashboard/dashboard.py @@ -721,16 +721,15 @@ def mail_rss(): """ return Response(rss_header + post_data + "\n\n", mimetype='text/xml') -@app.route('/api/', methods=['POST', 'GET']) +@app.route('/api', methods=['GET']) +@app.route('/api/', methods=['POST']) def api(api_mode=None): if request.method == 'GET': - print('get') + api_content = '

API Enabled: ' + str(use_api) + '

' return render_template('generic.html', title = dashboard_title, content = Markup(api_content)) - else: + if use_api == 'True' or use_api == "true": api_data = request.json - # Find out type of JSON - #print(api_data) - #print(authorized_users) + # Find out mode of JSON ## try: # Filter msg_xfer if api_data['mode'] == 'msg_xfer': @@ -758,31 +757,55 @@ def api(api_mode=None): status='Generated SMS', ) else: - return jsonify( - mode=api_data['mode'], - status='Authentication error', - ) + message = jsonify(message='Authentication error') + return make_response(message, 401) if api_data['auth_type'] == 'public': - return jsonify( - mode=api_data['mode'], - status='Not implemented at this time', - ) + message = jsonify(message='Not implemented') + return make_response(message, 403) else: - return jsonify( - mode=api_data['mode'], - status='Not an authorization method', - ) + message = jsonify(message='Not an authentication method') + return make_response(message, 400) if api_data['mode'] == 'app': - print('implement') + auth_file = ast.literal_eval(os.popen('cat ' + auth_token_file).read()) + for token in auth_file: + if token == api_data['auth_token']: + auth_file.remove(api_data['auth_token']) + for i in api_data['data'].items(): + sms_data = i[1] + if sms_data['slot'] == 0: + send_slot = int(unit_sms_ts) - 1 + if sms_data['slot'] == 1: + send_slot = 0 + if sms_data['slot'] == 2: + send_slot = 1 + send_sms(False, sms_data['destination_id'], sms_data['source_id'], 0000, 'unit', send_slot, sms_data['message']) + new_auth_file = auth_file + with open(auth_token_file, 'w') as auth_token: + auth_token.write(str(auth_file)) + auth_token.close() + + + return jsonify( + mode=api_data['mode'], + status='Token accepted, SMS generated', + ) + if token != api_data['auth_token']: + message = jsonify(message='Auth token not found') + return make_response(message, 401) + else: message = jsonify(message='Mode not found') - return make_response(message, 400) + return make_response(message, 404) + if use_api == "False" or use_api == "false": + message = jsonify(message='API is disabled for this server') + return make_response(message, 502) ## except Exception as e: ## message = jsonify(message='Error:' + str(e)) ## return make_response(message, 400) #################### Run App ############################ if __name__ == '__main__': + global use_api arg_parser = argparse.ArgumentParser() arg_parser.add_argument('-c', '--config', action='store', dest='CONFIG_FILE', help='/full/path/to/config.file (usually gps_data.cfg)') cli_args = arg_parser.parse_args() @@ -843,6 +866,19 @@ if __name__ == '__main__': the_mailbox_file = parser.get('GPS_DATA', 'MAILBOX_FILE') user_settings_file = parser.get('GPS_DATA', 'USER_SETTINGS_FILE') + auth_token_file = parser.get('GPS_DATA', 'AUTHORIZED_TOKENS_FILE') + use_api = parser.get('GPS_DATA', 'USE_API') + + #Only create if API enabled + if use_api == True: + if Path(auth_token_file).is_file(): + pass + else: + Path(auth_token_file).touch() + with open(auth_token_file, 'w') as auth_token: + auth_token.write("[]") + auth_token.close() + # API settings #authorized_apps_file = parser.get('GPS_DATA', 'AUTHORIZED_APPS_FILE') # Default SMS TS for unit calls