Ejemplo n.º 1
0
def push_message(ip_address, message):
    """ Connects to a client app and sends a message request """

    message = message + "\n"

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # get local machine name
    host = ip_address
    port = 5677

    print("connecting to socket: {}:{}".format(host, port))

    try:
        # connect to client
        s.connect((host, port))

        # prepare message
        message = message.encode("utf-8")

        sent = s.send(message)

        response_code = s.recv(1)

        s.close()
    except Error as e:
        return JSONResponse(False, "Socket error: {}".format(e))

    print("sent {} bytes. response: {}".format(sent, response_code))

    return JSONResponse(True)
Ejemplo n.º 2
0
 def post(self, *args) -> dict:
     serializer = AccountSerializer(data=self.request.data)
     if serializer.is_valid():
         serializer.save()
     else:
         return JSONResponse.badrequest(serializer.errors)
     return JSONResponse.success()
Ejemplo n.º 3
0
 def post(self, request) -> dict:
     serializer = FileSerializer(data=request.data, context=dict(request=request))
     if serializer.is_valid():
         serializer.save()
     else:
         return JSONResponse.badrequest(serializer.errors)
     return JSONResponse.success(serializer.data)
Ejemplo n.º 4
0
 def post(self, request, *args, **kwargs) -> dict:
     serializer = self.get_serializer(data=request.data)
     if serializer.is_valid():
         user = serializer.object.get('user') or request.user
         token = serializer.object.get('token')
         data = jwt_response_payload_handler(token, user, request)
         return JSONResponse.success(data)
     else:
         return JSONResponse.noauth(serializer.errors)
Ejemplo n.º 5
0
def logout(session):
    """ Logs a user out by destroying all session info. """

    if "username" not in session:
        return JSONResponse(False, "Not logged in")

    for k in session:
        del session[k]

    return JSONResponse(True)
    def put_action(self, url_params, form_data):
        service_row = self._get_service_row(form_data)

        if service_row is not None:
            result = self._model.update_row(url_params, service_row)
            if result:
                return JSONResponse(json_mes='row success updated')
            else:
                return JSONResponse(json_status='error', json_mes='error with updating row')
        else:
            logger.error(f'Not valid {form_data}')
            return BadResponse(400, 'Bad Request')
    def post_action(self, form_data):
        service_row = self._get_service_row(form_data)

        if service_row is not None:
            result = self._model.add_row(service_row)

            if result:
                return JSONResponse(json_mes='row success added')
            else:
                return JSONResponse(json_status='error', json_mes='error with adding row')
        else:
            logger.error(f'Not valid {form_data}')
            return BadResponse(400, 'Bad Request')
Ejemplo n.º 8
0
 def process_exception(request, exception):
     logger = logging.getLogger("api")
     info = traceback.format_exc()
     logger.error(info)
     if not settings.RETURN_ERR_INFO:
         info = "系统报错"
     return JSONResponse.servererr(info)
Ejemplo n.º 9
0
def get_message_route(requester_user, target_user):
    """ Looks up routing information for the given user.

    On a successful lookup, the following info should be returned:
        public_key: public key of the targeted user
        device_ip: last known IP of the targeted user
    """
    # Lookup public key and device ip of target
    try:
        cursor.execute(
            ("SELECT users.public_key, directory.device_ip FROM directory "
             "INNER JOIN users ON users.id = directory.user_id "
             "WHERE users.username=%s"), (target_user, ))
    except mariadb.Error as error:
        return JSONResponse(False, "Database error: {}".format(error))

    rows = cursor.fetchall()

    if len(rows) != 1:
        return JSONResponse(False,
                            "No directory entry found for given username")

    target_key, target_ip = rows[0]

    # Lookup public key and device ip of requester
    try:
        cursor.execute(
            ("SELECT users.public_key, directory.device_ip FROM directory "
             "INNER JOIN users ON users.id = directory.user_id "
             "WHERE users.username=%s"), (requester_user, ))
    except mariadb.Error as error:
        return JSONResponse(False, "Database error: {}".format(error))

    rows = cursor.fetchall()

    if len(rows) != 1:
        return JSONResponse(False,
                            "No directory entry found for given username")

    requester_key, requester_ip = rows[0]

    # Send requester ip and key to target (via socket to target)
    message = {}
    message["sender_ip"] = requester_ip
    message["sender_public_key"] = requester_key

    response = push_message(target_ip, json.dumps(message))

    if not response.success:
        return response

    # Return target ip and key to requester (via original http response)
    response = JSONResponse(True)
    response.target_ip = target_ip
    response.target_public_key = target_key

    return response
Ejemplo n.º 10
0
 def get(self, request, **kwargs) -> Union[dict, FileResponse]:
     file_id = kwargs.get("id")
     try:
         file = FileModel.objects.get(id=file_id)
     except FileModel.DoesNotExist:
         return JSONResponse.notfound("{}不指向任何文件".format(file_id))
     path = file.file.path
     name = file.name
     data = FileModel.read_iter_file(path)
     response = FileResponse(data)
     response['Content-Type'] = 'application/octet-stream'
     response['Content-Disposition'] = 'attachment;filename="{}"'.format(name).encode("utf-8")
     return response
Ejemplo n.º 11
0
    def upload_action(self, form_data):

        if not form_data['filename']:
            logger.error(f'Not valid {form_data} for file')
            return BadResponse(400, 'Bad Request')
        elif not form_data['filename'].endswith('.csv'):
            logger.error(f'Not valid {form_data["filename"]}')
            return BadResponse(400, 'Bad Request')

        path_to_file = self._save_file(form_data)

        if path_to_file is None:
            return JSONResponse(json_status='error',
                                json_mes='error with saving file')

        result = self._model.upload_data(path_to_file)

        os.remove(path_to_file)

        if result:
            return JSONResponse(json_mes='table success updated from file')
        else:
            return JSONResponse(json_status='error',
                                json_mes='error with updating table from file')
Ejemplo n.º 12
0
def create_account_post():
    """ Creates a new account. """

    response = JSONResponse()

    # Check login status and privileges
    if "username" not in session:
        session["create_account_error"] = "You must be logged in"
        return redirect("/cryptic/admin/console")

    if "is_admin" in session:
        if session["is_admin"] < accounts.ADMIN:
            session[
                "create_account_error"] = "Insufficient privileges for account creation"
            return redirect("/cryptic/admin/console")
    else:
        session[
            "create_account_error"] = "Insufficient privileges for account creation"
        return redirect("/cryptic/admin/console")

    # Form validation
    if "username" not in request.form:
        session[
            "create_account_error"] = "No username provided for account creation"
        return redirect("/cryptic/admin/console")

    username = request.form["username"]

    if len(username) > 255 or len(username) < 3:
        session[
            "create_account_error"] = "Username must be between 3 and 255 characters"
        return redirect("/cryptic/admin/console")

    response = accounts.create_account(session, username)

    if response.success:
        session["create_account_success"] = True
    else:
        session["create_account_error"] = response.message

    return redirect("/cryptic/admin/console")
Ejemplo n.º 13
0
def create_account(session, username):
    """ Attempts to create the given user account.

    The user calling this method must have admin privileges to create a new
    user account.

    Returns: a tuple (success, message) detailing the result of the login
             attempt
    """

    # Ensure username is not taken
    try:
        cursor.execute("SELECT username FROM users WHERE username=%s",
                       (username, ))
    except mariadb.Error as error:
        return JSONResponse(False, "Database error: {}".format(error))

    rows = cursor.fetchall()

    if len(rows) > 0:
        return JSONResponse(False, "Username is already taken")

    # Generate a random password. This must be sent to the account creator
    gen_password = generate_password()
    gen_password = gen_password.encode("UTF-8")
    hashed_password = bcrypt.hashpw(gen_password, bcrypt.gensalt())

    session["generated_password"] = gen_password

    # Personal key generation for message storage
    personal_key = generate_personal_key()

    # Insert new account into database
    try:
        cursor.execute(
            "INSERT INTO users (username, password, personal_key) VALUES (%s, %s, %s)",
            (username, hashed_password, personal_key))
    except mariadb.Error as error:
        return JSONResponse(False, "Database error: {}".format(error))

    # Commit transaction
    db_conn.commit()

    # Successful insert. Prepare response for client
    response = JSONResponse(True)
    response.password = gen_password

    return response
Ejemplo n.º 14
0
def login_post():
    """ Handles login requests. """

    if "login_error" in session:
        del session["login_error"]

    response = JSONResponse()

    if "medium" in request.form and request.form["medium"] == "admin_web":
        # request is from web

        # Form validation
        if "username" not in request.form:
            session["login_error"] = "No username provided for login"
            return redirect("/cryptic/admin/login")

        if "password" not in request.form:
            rsession["login_error"] = "No password provided for login"
            return redirect("/cryptic/admin/login")

        username = request.form["username"]
        password = request.form["password"]

        if len(username) > 255:
            session["login_error"] = "Username may not exceed 255 characters"
            return redirect("/cryptic/admin/login")

        if len(password) > 255:
            session["login_error"] = "Password may not exceed 255 characters"
            return redirect("/cryptic/admin/login")

        # Check for active sessions
        if "username" in session:
            print("username in session found: ", session["username"])
            # Client is already logged in as someone
            if session["username"] == username:
                # Already logged in as person who they are trying to login as
                return redirect("/cryptic/admin/console")
            else:
                session.clear()
                #session["login_error"] = "You are already logged in as someone else"
                #return redirect("/cryptic/admin/login")

        # Perform login
        response = accounts.login(session, username, password, None, None)

        if response.success:
            return redirect("/cryptic/admin/console")

        session["login_error"] = response.message
        return redirect("/cryptic/admin/login")

    else:
        # assume request is from app

        # Form validation
        if "username" not in request.form:
            response.success = False
            response.message = "No username provided for login"
            return response.to_json(), 200

        if "password" not in request.form:
            response.success = False
            response.message = "No password provided for login"
            return response.to_json(), 200

        username = request.form["username"]
        password = request.form["password"]

        device_ip = request.form[
            "device_ip"] if "device_ip" in request.form else ""

        if "public_key" in request.form:
            public_key = request.form["public_key"]

            if public_key == "PLACEHOLDER_KEY_IGNORE":
                public_key = None
        else:
            public_key = None

        if len(username) > 255:
            response.success = False
            response.message = "Username field may not exceed 255 characters"
            return response.to_json(), 200

        if len(password) > 255:
            response.success = False
            response.message = "Password field may not exceed 255 characters"
            return response.to_json(), 200

        # Check for active sessions
        if "username" in session:
            print("username in session found: ", session["username"])
            # Client is already logged in as someone
            if session["username"] == username:
                # Already logged in as person who they are trying to login as
                response.success = True
            else:
                response.success = False
                response.message = "You are already logged in as someone else"
            return response.to_json(), 200

        # Perform login
        response = accounts.login(session, username, password, device_ip,
                                  public_key)

        return response.to_json(), 200
Ejemplo n.º 15
0
 def delete_action(self, url_params):
     result = self._model.delete_row(url_params)
     if result:
         return JSONResponse(json_mes='row success deleted')
     else:
         return JSONResponse(json_status='error', json_mes='error with deleting row')
Ejemplo n.º 16
0
 def get_action(self):
     result = self._model.get_all()
     return JSONResponse(data=result)
Ejemplo n.º 17
0
 def post(self, request, **kwargs):
     user_ids = request.data.get("user_ids")
     data = {'text': 'websocket成功'}
     mass_message(user_ids, data)
     return JSONResponse.success()
Ejemplo n.º 18
0
 def get(self, request: Request, **kwargs) -> dict:
     user_id = request.user.id
     data = {'text': 'websocket成功'}
     send_message.delay(user_id, data)
     return JSONResponse.success()
Ejemplo n.º 19
0
 def delete(self, request, **kwargs) -> dict:
     file_id = kwargs.get("id")
     FileModel.objects.filter(id=file_id).delete()
     return JSONResponse.success()
Ejemplo n.º 20
0
def message_route():
    """ Mediate peer-to-peer connections.

    Expected request parameters:
        target: the user that we are requesting a route to

    Returns:
        JSONResponse detailing the request result
    """

    response = JSONResponse()

    # Check login status
    if "username" not in session:
        response.success = False
        response.message = "You must be logged in to request a route"
        return response.to_json(), 200

    requester = session["username"]

    # Form validation
    if "target" not in request.form:
        response.success = False
        response.message = "No target provided for routing"
        return response.to_json(), 200

    target = request.form["target"]

    if len(target) > 255:
        response.success = False
        response.message = "Target user field may not exceed 255 characters"
        return response.to_json(), 200

    response = routing.get_message_route(requester, target)

    return response.to_json(), 200
Ejemplo n.º 21
0
def login(session, username, password, device_ip, public_key):
    """ Attempts to login the given user with the given password.

    Returns: a JSONResponse object detailing the result of the login request
    """

    # Find user in DB
    try:
        cursor.execute(
            "SELECT id, username, password, is_admin, personal_key FROM users WHERE username=%s",
            (username, ))
    except mariadb.Error as error:
        return JSONResponse(False, "Database error: {}".format(error))

    rows = cursor.fetchall()

    if len(rows) != 1:
        return JSONResponse(False, "Invalid username or password")

    user_id, fetched_username, hashed_password, is_admin, personal_key = rows[
        0]

    # Encode passwords for use in bcrypt
    password = password.encode("UTF-8")
    hashed_password = hashed_password.encode("UTF-8")

    if bcrypt.checkpw(password, hashed_password):
        # Login was successful
        session["username"] = fetched_username
        session["is_admin"] = is_admin
    else:
        # Invalid password
        return JSONResponse(False, "Invalid username or password")

    # If we are here, login was succesful

    # save device ip if given
    if device_ip:

        # check for existing directory entry
        try:
            cursor.execute(
                "SELECT device_ip FROM directory INNER JOIN users ON users.id = directory.user_id WHERE username=%s",
                (username, ))
        except mariadb.Error as error:
            return JSONResponse(False, "Database error: {}".format(error))

        rows = cursor.fetchall()

        if len(rows) == 1:
            # run update if different
            fetched_ip = rows[0]

            if fetched_ip != device_ip:
                try:
                    cursor.execute(
                        "UPDATE directory INNER JOIN users ON users.id = directory.user_id SET device_ip=%s WHERE username=%s",
                        (device_ip, username))
                except mariadb.Error as error:
                    return JSONResponse(False,
                                        "Database error: {}".format(error))
                db_conn.commit()
        else:
            # run insert
            try:
                cursor.execute(
                    "INSERT INTO directory (user_id, device_ip) VALUES (%s, %s)",
                    (user_id, device_ip))
            except mariadb.Error as error:
                return JSONResponse(False, "Database error: {}".format(error))
            db_conn.commit()

    # save public key if given
    if public_key:
        try:
            cursor.execute("UPDATE users SET public_key=%s WHERE username=%s",
                           (public_key, username))
        except mariadb.Error as error:
            return JSONResponse(False, "Database error: {}".format(error))
        db_conn.commit()

    response = JSONResponse(True)

    if personal_key:
        response.personal_key = personal_key

    return response