async def start_server(): grpc_port = get_system_config()['grpc_port'] server = grpc.aio.server() # server = grpc.server(futures.ThreadPoolExecutor(max_workers=10), interceptors=(AuthInterceptor(),)) # server = grpc.server(futures.ThreadPoolExecutor(max_workers=200)) user_service.add_UserServicer_to_server(UserController(), server) auth_service.add_AuthServicer_to_server(AuthController(), server) signal_service.add_SignalKeyDistributionServicer_to_server(SignalController(), server) group_service.add_GroupServicer_to_server(GroupController(), server) message_service.add_MessageServicer_to_server(MessageController(), server) notify_inapp_service.add_NotifyServicer_to_server(NotifyInAppController(), server) notify_push_service.add_NotifyPushServicer_to_server(NotifyPushController(), server) video_call_service.add_VideoCallServicer_to_server(VideoCallController(), server) server_info_service.add_ServerInfoServicer_to_server(ServerInfoController(), server) upload_file_service.add_UploadFileServicer_to_server(UploadFileController(), server) workspace_service.add_WorkspaceServicer_to_server(WorkspaceController(), server) note_service.add_NoteServicer_to_server(NoteController(), server) # init log os.makedirs("logs", exist_ok=True) create_timed_rotating_log('logs/logfile-' + str(grpc_port) + '.log') # start grpc api grpc_add = "0.0.0.0:{}".format(grpc_port) server.add_insecure_port(grpc_add) await server.start() print("gRPC listening on port {}..".format(grpc_port)) logger.info("gRPC listening on port {}..".format(grpc_port)) try: await server.wait_for_termination() except KeyboardInterrupt: await server.stop(0)
def get_upload_file_link(self, file_name, file_type, uploader, access_control_list='private', expiration=3600): # get pre presigned url for directly upload file s3_config = get_system_config()['storage_s3'] file_path = os.path.join(s3_config.get('folder'), uploader, str(round(time.time() * 100)), file_name) s3_client = boto3.client( 's3', aws_access_key_id=s3_config.get('access_key_id'), aws_secret_access_key=s3_config.get('access_key_secret')) url_response = s3_client.generate_presigned_url( 'put_object', Params={ 'Bucket': s3_config.get('bucket'), 'Key': file_path, 'ContentType': file_type, 'ACL': access_control_list }, ExpiresIn=expiration) if access_control_list in ['public-read', 'public-read-write']: file_url = os.path.join(s3_config.get('url'), s3_config.get('bucket'), file_path) else: file_url = "" return upload_file_pb2.GetUploadFileLinkResponse( uploaded_file_url=url_response, download_file_url=file_url, object_file_path=file_path)
def _fd_server_check(ip_address): config = get_system_config() for item in config['fd_server']: logger.info({"ip_address": item.get('ip_address', "Not found")}) if item['ip_address'] in ip_address: return True return False
class MailerServer(object): host = get_system_config()["smtp_server"]['SMTP_HOST'] port = get_system_config()["smtp_server"]['SMTP_PORT'] sender_display_name = "ClearKeep" sender = get_system_config()["smtp_server"]['SMTP_SENDER'] user_name = get_system_config()["smtp_server"]['SMTP_USERNAME'] password = get_system_config()["smtp_server"]['SMTP_PASSWORD'] query_string_form = "pre_access_token={}&user_name={}&server_domain={}" app_link = "http://www.clearkeep.com/resetpassword" text_form = """Your administrator has just requested that you update your Keycloak account by performing the following action(s): Reset Password. Click on the link below to start this process.\n {}\n This link will expire within 30 days. If you are unaware that your administrator has requested this, just ignore this message and nothing will be changed. """ html_form = """ <p>Your administrator has just requested that you update your Keycloak account by performing the following action(s): Reset Password. Click on the link below to start this process.\n</p> <p><a clicktracking=off href="{}">Link to account update</a></p> <p>This link will expire within 30 days.</p> <p>If you are unaware that your administrator has requested this, just ignore this message and nothing will be changed.</p> """ @staticmethod def send_reset_password_mail(receiver_mail, user_name, pre_access_token, server_domain): # Email configuration deep_link = MailerServer.app_link + '?' + MailerServer.query_string_form.format(pre_access_token, user_name, server_domain) msg = MIMEMultipart('alternative') msg['Subject'] = 'Reset Password' msg['From'] = format_addresses([(MailerServer.sender_display_name, MailerServer.sender)], header_name='from') msg['To'] = receiver_mail text = MailerServer.text_form.format(deep_link) html = MailerServer.html_form.format(deep_link) part1 = MIMEText(text, 'plain') part2 = MIMEText(html, 'html') msg.attach(part1) msg.attach(part2) server = smtplib.SMTP_SSL(MailerServer.host, MailerServer.port) server.ehlo() server.login(MailerServer.user_name, MailerServer.password) server.sendmail( MailerServer.sender, receiver_mail, msg.as_string() ) server.quit()
async def start_http_server(): # start http api http_port = get_system_config()['http_port'] print("HTTP listening on port {}..".format(http_port)) logger.info("HTTP listening on port {}..".format(http_port)) app.run(host="0.0.0.0", port=str(http_port), threaded=False, processes=3, debug=False)
def facebook_login(self, facebook_access_token): # facebook login by using facebook access token, return user_name, user_id and boolean variable indicate if this user is new user try: # validate access_token facebook_app_id = get_system_config()["facebook_app"] verify_token_app_id = "https://graph.facebook.com/debug_token?input_token={}&access_token={}|{}".format( facebook_access_token, facebook_app_id["app_id"], facebook_app_id["app_secret"]) req = requests.get(url=verify_token_app_id) if req.status_code != 200: raise Exception(Message.FACEBOOK_ACCESS_TOKEN_INVALID) facebook_token_app_id_info = req.json() facebook_token_app_id = facebook_token_app_id_info["data"][ "app_id"] if facebook_token_app_id != facebook_app_id["app_id"]: raise Exception(Message.FACEBOOK_ACCESS_TOKEN_INVALID) verify_token_url = "https://graph.facebook.com/me?fields=id,name,email&access_token=" + facebook_access_token req = requests.get(url=verify_token_url) if req.status_code != 200: raise Exception(Message.FACEBOOK_ACCESS_TOKEN_INVALID) facebook_token_info = req.json() logger.info("Facebook login token spec:") logger.info(facebook_token_info) facebook_id = facebook_token_info["id"] facebook_email = facebook_token_info["email"] facebook_name = facebook_token_info["name"] # check account exits user = self.get_user_by_email(facebook_id) if user: user_info = UserService().get_user_by_id(user["id"]) return facebook_id, user[ "id"], user_info.password_verifier is None or user_info.password_verifier == "" else: # create new user new_user_id = KeyCloakUtils.create_user_without_password( facebook_email, facebook_id, "", facebook_name) new_user = UserService().create_user_social( id=new_user_id, email=facebook_email, display_name=facebook_name, auth_source='facebook') if new_user is None: self.delete_user(new_user_id) raise Exception(Message.REGISTER_USER_FAILED) return facebook_id, new_user_id, True except Exception as e: logger.info(e) raise Exception(Message.FACEBOOK_AUTH_FAILED)
def remove_client_token(self, token): # remove a client calling token for janus_webrtc webrtc_config = get_system_config()["janus_webrtc"] transaction = str(uuid.uuid4()).replace("-", "") payload = { "janus": "remove_token", "token": token, "transaction": transaction, "admin_secret": webrtc_config["admin_secret"] } response = requests.post(webrtc_config["server_url"], payload) if response["janus"] == "success": return True else: return False
def upload_to_s3(self, file_name, file_data, content_type): # s3 uploader s3_config = get_system_config()['storage_s3'] file_path = os.path.join(s3_config.get('folder'), file_name) s3_client = boto3.client( 's3', aws_access_key_id=s3_config.get('access_key_id'), aws_secret_access_key=s3_config.get('access_key_secret')) s3_client.put_object(Body=file_data, Bucket=s3_config.get('bucket'), Key=file_path, ContentType=content_type, ACL='public-read') uploaded_file_url = os.path.join(s3_config.get('url'), s3_config.get('bucket'), file_path) return uploaded_file_url
def get_download_file_link(self, file_path, downloader, expiration=3600): # get pre presigned url for directly download file assert downloader != "" # verify reading access of downloader s3_config = get_system_config()['storage_s3'] s3_client = boto3.client( 's3', aws_access_key_id=s3_config.get('access_key_id'), aws_secret_access_key=s3_config.get('access_key_secret')) url_response = s3_client.generate_presigned_url( 'get_object', Params={ 'Bucket': s3_config.get('bucket'), 'Key': file_path }, ExpiresIn=expiration) return upload_file_pb2.GetDownloadFileLinkResponse( download_file_url=url_response)
def google_login(self, google_id_token): # google login by using google id token, return user_name, user_id and boolean variable indicate if this user is new user try: verify_id_token_url = "https://oauth2.googleapis.com/tokeninfo?id_token=" + google_id_token req = requests.get(url=verify_id_token_url) if req.status_code != 200: raise Exception(Message.GOOGLE_AUTH_ID_TOKEN_INVALID) google_token_info = req.json() logger.info("Google login token spec:") logger.info(google_token_info) # check google_token_info["aud"] matching with google app id google_app_id = get_system_config()["google_app_id"] if google_token_info["aud"] != google_app_id[ "ios"] and google_token_info["aud"] != google_app_id[ "android"]: raise Exception(Message.GOOGLE_AUTH_FAILED) google_email = google_token_info["email"] # check account exits user = self.get_user_by_email(email=google_email) #active_user if user: if not user["emailVerified"]: KeyCloakUtils.active_user(user["id"]) user_info = UserService().get_user_by_id(user["id"]) return google_email, user[ "id"], user_info.password_verifier is None or user_info.password_verifier == "" else: # create new user new_user_id = KeyCloakUtils.create_user_without_password( google_email, google_email, "", google_token_info["name"]) new_user = UserService().create_user_social( id=new_user_id, email=google_email, display_name=google_token_info["name"], auth_source='google') if new_user is None: self.delete_user(new_user_id) raise Exception(Message.REGISTER_USER_FAILED) return google_email, new_user_id, True except Exception as e: logger.info(e) raise Exception(Message.GOOGLE_AUTH_FAILED)
def get_owner_workspace_client_status(self, client_id): # get client record of client_id in this server client_record = client_records_list_in_memory.get(str(client_id), None) if client_record is not None: leave_time_amount = datetime.datetime.now( ) - client_record["last_active"] if leave_time_amount.seconds > get_system_config().get( "maximum_offline_time_limit"): user_status = "Offline" else: if client_record["user_status"] is not None: user_status = client_record["user_status"] else: user_status = "Online" else: user_status = "Undefined" return user_status
def update_stun_turn_credential(): print('Cronjob Run At: ' + str(datetime.now())) data = get_system_config() stun, turn = generate_stun_turn_credential(data) host = data['server_domain'] port = data['grpc_port'] try: # update for production branch channel = grpc.insecure_channel(host + ':' + str(port)) stub = server_info_pb2_grpc.ServerInfoStub(channel) request = server_info_pb2.UpdateNTSReq(stun=stun, turn=turn) stub.update_nts(request) except Exception as e: logger.error(e) try: #update for stagging branch channel2 = grpc.insecure_channel(host + ':1' + str(port)) stub2 = server_info_pb2_grpc.ServerInfoStub(channel2) request2 = server_info_pb2.UpdateNTSReq(stun=stun, turn=turn) stub2.update_nts(request2) except Exception as e: logger.error(e) try: # update for dev branch channel3 = grpc.insecure_channel(host + ':2' + str(port)) stub3 = server_info_pb2_grpc.ServerInfoStub(channel3) request3 = server_info_pb2.UpdateNTSReq(stun=stun, turn=turn) stub3.update_nts(request3) except Exception as e: logger.error(e) print('Set cronjob succesful')
# ref https://pypi.org/project/python-keycloak/ from keycloak import KeycloakOpenID, KeycloakAdmin from keycloak import raise_error_from_response from keycloak import KeycloakGetError from utils.config import get_system_config import json URL_ADMIN_REMOVE_USER_SESSIONS = "admin/realms/{realm-name}/users/{id}/logout" URL_ADMIN_REMOVE_SESSION = "admin/realms/{realm-name}/sessions/{session}" # keycloak client config_keycloak_client = get_system_config()['keycloak_account'] keycloak_openid = KeycloakOpenID( server_url=config_keycloak_client['server_url'], client_id=config_keycloak_client['client_id'], realm_name=config_keycloak_client['realm_name'], client_secret_key=config_keycloak_client['client_secret_key']) # keycloak admin config_keycloak_admin = get_system_config()['keycloak_admin'] keycloak_admin = KeycloakAdmin( server_url=config_keycloak_admin['server_url'], username=config_keycloak_admin['username'], password=config_keycloak_admin['password'], realm_name=config_keycloak_admin['realm_name'], client_secret_key=config_keycloak_admin['client_secret_key'], verify=True, auto_refresh_token=['get', 'put', 'post', 'delete']) class KeyCloakUtils: @staticmethod
# need to import for create all table from src.models.group import GroupChat from src.models.message import Message from src.models.notify import Notify from src.models.notify_token import NotifyToken from src.models.server_info import ServerInfo from src.models.signal_group_key import GroupClientKey from src.models.signal_peer_key import PeerClientKey from src.models.user import User from src.models.message_user_read import MessageUserRead #from src.models.workspace import Workspace from src.models.video_call import VideoCall from src.models.note import Note from src.models.authen_setting import AuthenSetting db_config = get_system_config()['db'] db_connection = 'postgresql://{user}:{pw}@{host}:{port}/{db}'.format( user=db_config['username'], pw=db_config['password'], host=db_config['host'], port=db_config['port'], db=db_config['name']) app = Flask(__name__) csrf = CSRFProtect(app) app.config['SQLALCHEMY_DATABASE_URI'] = db_connection app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config["SQLALCHEMY_ECHO"] = True app.config["SQLALCHEMY_POOL_SIZE"] = 30 app.config["SQLALCHEMY_POOL_TIMEOUT"] = 300 app.config["SQLALCHEMY_MAX_OVERFLOW"] = -1
from kalyke.client import VoIPClient, APNsClient from utils.config import get_system_config import firebase_admin from firebase_admin import credentials, messaging from utils.logger import logger from kalyke.payload import PayloadAlert, Payload import time # init push service for iOS client_ios_voip = VoIPClient( auth_key_filepath=get_system_config()["device_ios"].get( 'certificates_voip'), bundle_id=get_system_config()["device_ios"].get('bundle_id'), use_sandbox=get_system_config()["device_ios"].get('use_sandbox')) client_ios_text = APNsClient( team_id=get_system_config()["device_ios"].get('team_id'), auth_key_id=get_system_config()["device_ios"].get('auth_key_id'), auth_key_filepath=get_system_config()["device_ios"].get( 'certificates_apns'), bundle_id=get_system_config()["device_ios"].get('bundle_id'), use_sandbox=get_system_config()["device_ios"].get('use_sandbox'), force_proto="h2", apns_push_type="alert") # init push service for Android cred = credentials.Certificate( get_system_config()["device_android"].get("fire_base_config")) default_app = firebase_admin.initialize_app(cred)