Code Monkey home page Code Monkey logo

Comments (18)

Ali-RAFIEE avatar Ali-RAFIEE commented on July 22, 2024 1

Hi Davide
Thanks a lot.

from remi.

dddomodossola avatar dddomodossola commented on July 22, 2024

Hello,

Remi allows to create graphical interfaces for python applications. Such interfaces are accessible from everywhere in your network. I suggest to only expose such applications in private networks or VPN.

Kind Regards.

from remi.

Ali-RAFIEE avatar Ali-RAFIEE commented on July 22, 2024

Thanks Davide,
I have some experiace with TKinter for standalone app, but now I need a tool like Remi to convert my codes to network user (in VPN format), so I think Remi can be appropaite for this purpose.

I need just a small script to found out how I can create an shared interface under SAAS form.
Thanks again

from remi.

dddomodossola avatar dddomodossola commented on July 22, 2024

I would be pleaded to help you, but you should give me more details about the requirements. Remi allows to create ui. SaaS is a sw architecture to make an application running as a service, maybe giving it a REST interface. Here we have two different things.. what you want to do exactly?

from remi.

Ali-RAFIEE avatar Ali-RAFIEE commented on July 22, 2024

I would like to create an interface for a code, that a user on our internal network can run it from his pc (remote access, without having access to the code, just by having access to the web interface), then the user can give and change some parameters and may be able to view results (calculation results) and some generated graphes.

from remi.

dddomodossola avatar dddomodossola commented on July 22, 2024

There are different examples about remi in this folder
https://github.com/rawpython/remi/tree/master/examples

Additionally there is a graphical editor that can help you design your interface.

from remi.

Ali-RAFIEE avatar Ali-RAFIEE commented on July 22, 2024

already I tested some of them, but a problem that I have, is how can I run one simple exmple in this series of test codes from another pc.
I can not configure IP adresse inside of code, to have acces from another pc.

So, real issue it s how can I configure acces with IP adresse ou other way to arrive runing graphic interface via remote PC.

Thanks a lot

from remi.

dddomodossola avatar dddomodossola commented on July 22, 2024

At the end of the script there is the "start" function call, there an ip address is passed as parameter. Set that ip address as 0.0.0.0 and the ui will be reachable from every device in the network

from remi.

Ali-RAFIEE avatar Ali-RAFIEE commented on July 22, 2024

I try one example on same wifi connection

I have GUI on my runing PC with this adresse http://127.0.0.1:8081/

but I can not see the same page from another PC.

it is not work for me!!

from remi.

dddomodossola avatar dddomodossola commented on July 22, 2024

On the other machine you should access a different url. The ip address in the url must be the ipaddress of the machine running the application.
http://correct_ip:8081/

from remi.

dddomodossola avatar dddomodossola commented on July 22, 2024

@Ali-RAFIEE did you get it working?

from remi.

Ali-RAFIEE avatar Ali-RAFIEE commented on July 22, 2024

Thank you very much Davide
That works.

but is it possible to convert the access into a https secure access?
and also how can i get my code to run directly from a remote PC?

Thanks.

from remi.

dddomodossola avatar dddomodossola commented on July 22, 2024

I'm pleased to help.
Of course it is possible to use https, but you need to create certificates.
You can run your program on every kind of machine, and you can access your interface from everywhere. What you mean for executing the code directly from the remote PC?

from remi.

Ali-RAFIEE avatar Ali-RAFIEE commented on July 22, 2024

currently I run my code on my PC and I manage to have the Gui interface on another PC.
but in fact I would like to run the code directly from the remote pc without having to run it first on the PC hosting the code.

from remi.

Ali-RAFIEE avatar Ali-RAFIEE commented on July 22, 2024

Do I have to keep the main interface open all the time on the server PC to run a code?

Indeed I want to have the first page which checks the username and password of each user, then if a user wants to do calculations he can perform and at the same time the software home page can accept multiple users simultaneously. Is it possible with Remi? Any simple example?

Thanks a lot

from remi.

dddomodossola avatar dddomodossola commented on July 22, 2024

You have to run the script on the server. You can open and close the interface when you want, the server will continue to listen for new connections. Of course different users can connect to the interface at the same time and perform login separately

from remi.

Ali-RAFIEE avatar Ali-RAFIEE commented on July 22, 2024

And last question:
should I create two separate pages, one for logging (verifying username and password) and another to give access to the user to run the main code?

and how can I manage to get multiple users working simultaneously with the same code but with different inputs and therefore different results to illustrate? should I generate a different port number for each new user?

if there is a simple example it is welcome, starting a new challenge is always a harder part of a project.

Thanks again

from remi.

dddomodossola avatar dddomodossola commented on July 22, 2024

Hello @Ali-RAFIEE ,

Here is an example for you. It is an advanced example, I'm sure you can simplify it.

import remi.gui as gui
from remi.gui import *
from remi import start, App
import random
import threading

class CookieInterface(gui.Tag, gui.EventSource):
    def __init__(self, remi_app_instance, **kwargs):
        super(CookieInterface, self).__init__(**kwargs)
        gui.EventSource.__init__(self)
        self.app_instance = remi_app_instance
        self.EVENT_ONCOOKIES = "on_cookies"
        self.cookies = {}
        
    def request_cookies(self):
        self.app_instance.execute_javascript("""
            var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);
            var result = {};
            for (var nLen = aKeys.length, nIdx = 0; nIdx < nLen; nIdx++) { 
                var key = decodeURIComponent(aKeys[nIdx]);
                result[key] = decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(key).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null; 
            }
            sendCallbackParam('%s','%s', result);
            """%(self.identifier, self.EVENT_ONCOOKIES))

    @gui.decorate_event
    def on_cookies(self, **value):
        self.cookies = value
        return (value,)
    
    def remove_cookie(self, key, path='/', domain=''):
        if not key in self.cookies.keys():
            return
        self.app_instance.execute_javascript( """
            var sKey = "%(sKey)s";
            var sPath = "%(sPath)s";
            var sDomain = "%(sDomain)s";
            document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "");
            """%{'sKey': key, 'sPath': path, 'sDomain': domain} )

    def set_cookie(self, key, value, expiration='Infinity', path='/', domain='', secure=False):
        """
        expiration (int): seconds after with the cookie automatically gets deleted
        """

        secure = 'true' if secure else 'false'
        self.app_instance.execute_javascript("""
            var sKey = "%(sKey)s";
            var sValue = "%(sValue)s";
            var vEnd = eval("%(vEnd)s");
            var sPath = "%(sPath)s"; 
            var sDomain = "%(sDomain)s"; 
            var bSecure = %(bSecure)s;
            if( (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) == false ){
                var sExpires = "";
                if (vEnd) {
                    switch (vEnd.constructor) {
                        case Number:
                            sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
                        break;
                        case String:
                            sExpires = "; expires=" + vEnd;
                        break;
                        case Date:
                            sExpires = "; expires=" + vEnd.toUTCString();
                        break;
                    }
                }
                document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");
            }
            """%{'sKey': key, 'sValue': value, 'vEnd': expiration, 'sPath': path, 'sDomain': domain, 'bSecure': secure})


class User(object):
    USER_LEVEL_NOT_AUTHENTICATED = 0
    USER_LEVEL_USER = 1
    USER_LEVEL_ADMIN = 2

    def __init__(self, username, pwd, user_level=0):
        self.username = username
        self.pwd = pwd
        self.user_level = user_level


class LoginManager(gui.Tag, gui.EventSource):
    """
    Login manager class allows to simply manage user access safety by session cookies
    It requires a cookieInterface instance to query and set user session id
    When the user login to the system you have to call
        login_manager.renew_session() #in order to force new session uid setup

    The session have to be refreshed each user action (like button click or DB access)
    in order to avoid expiration. BUT before renew, check if expired in order to ask user login

        if not login_manager.expired:
            login_manager.renew_session()
            #RENEW OK
        else:
            #UNABLE TO RENEW
            #HAVE TO ASK FOR LOGIN

    In order to know session expiration, you should register to on_session_expired event
        on_session_expired.do(mylistener.on_user_logout)
    When this event happens, ask for user login
    """
    def __init__(self, user_dictionary, cookieInterface, session_timeout_seconds = 60, **kwargs):
        #user_dictionary is a  dictionary (the key is the username, 
        # the value is a User instance) have to be a list of users, can be loaded or other data sources
        super(LoginManager, self).__init__(**kwargs)
        gui.EventSource.__init__(self)
        self.user_dictionary = user_dictionary 
        self.user_logged_instance = None
        self.session_uid = str(random.randint(1,999999999))
        self.cookieInterface = cookieInterface
        self.session_timeout_seconds = session_timeout_seconds
        self.timer_request_cookies() #starts the cookie refresh
        self.timeout_timer = None #checks the internal timeout
    
    def timer_request_cookies(self):
        self.cookieInterface.request_cookies()
        threading.Timer(self.session_timeout_seconds/10.0, self.timer_request_cookies).start()

    @gui.decorate_event
    def on_session_expired(self):
        self.user_logged_instance = None
        return ()

    def renew_session(self):
        """Have to be called on user actions to check and renew session
        """
        if ((not 'user_uid' in self.cookieInterface.cookies) or self.cookieInterface.cookies['user_uid']!=self.session_uid) and (not (self.user_logged_instance==None)):
            self.on_session_expired()

        if self.user_logged_instance == None:
            self.session_uid = str(random.randint(1,999999999))
        
        self.cookieInterface.set_cookie('user_uid', self.session_uid, str(self.session_timeout_seconds))

        #here we renew the internal timeout timer
        if self.timeout_timer:
            self.timeout_timer.cancel()
        self.timeout_timer = threading.Timer(self.session_timeout_seconds, self.on_session_expired)
        self.timeout_timer.start()

    def login(self, username, pwd):
        #returns None if not authenticated or a User instance, with the proper user_level
        if username in self.user_dictionary.keys():
            if pwd == self.user_dictionary[username].pwd:
                print("password ok")
                self.user_logged_instance = self.user_dictionary[username]
                self.renew_session()
                return self.user_dictionary[username] #self.user_logged_instance
        return None

    def add_user(self, user):
        #add a new user that can login, you can save it to a database
        self.user_dictionary[user.username] = user


class ContainerProxy():
    #given a container, this class allows to append widgets to it, keeping memory about widget user level.
    # when user level changes, this class hides or shows children widgets properly
    def __init__(self, container):
        self.container = container
        self.widgets_dictionary = {}

    def append(self, user_level, widget, key=None):
        key = self.container.append(widget, key)
        #here we store for each widget, the minimum user level for which it have to be visible 
        self.widgets_dictionary[key] = {'widget':widget, 'user_level':user_level}

    def set_logged_user_level(self, user_level = User.USER_LEVEL_NOT_AUTHENTICATED):
        self.user_level = user_level
        for widget_id in self.widgets_dictionary.keys():
            if self.widgets_dictionary[widget_id]['user_level'] > self.user_level:
                #here we replace the widget to hide in order to mantain a placeholder
                self.container.append(gui.Widget(style={'display':'none', 'width':'0px', 'height':'0px'}), widget_id)
            else:
                #here we put again the widget on the interface, the placeholder gets replaced because the same kay is used to append
                self.container.append(self.widgets_dictionary[widget_id]['widget'], widget_id)


class MyApp(App):
    def __init__(self, *args, **kwargs):
        super(MyApp, self).__init__(*args, static_file_path='./res/')

    def idle(self):
        #idle function called every update cycle
        pass
    
    def main(self):
        main_container = Container(margin="0px auto")
        self.container_proxy = ContainerProxy(main_container)
        main_container.attributes.update({"editor_baseclass":"Container","editor_tag_type":"widget","editor_newclass":"False","editor_constructor":"()","class":"Container","editor_varname":"main_container"})
        main_container.style.update({"width":"580.0px","position":"relative","overflow":"auto","height":"500.0px"})
        user_area_container = Container()
        user_area_container.attributes.update({"editor_baseclass":"Container","editor_tag_type":"widget","editor_newclass":"False","editor_constructor":"()","class":"Container","editor_varname":"user_area_container"})
        user_area_container.style.update({"width":"260.0px","border-style":"dotted","border-width":"1px","position":"absolute","top":"40.0px","left":"20.0px","margin":"0px","overflow":"auto","height":"440.0px"})
        lbl_user_panel = Label('User panel')
        lbl_user_panel.attributes.update({"editor_baseclass":"Label","editor_tag_type":"widget","editor_newclass":"False","editor_constructor":"('User panel')","class":"Label","editor_varname":"lbl_user_panel"})
        lbl_user_panel.style.update({"width":"100px","position":"absolute","top":"20.0px","left":"20.0px","margin":"0px","overflow":"auto","height":"30px"})
        user_area_container.append(lbl_user_panel,'lbl_user_panel')
        #main_container.append(user_area_container,'user_area_container')
        self.container_proxy.append(User.USER_LEVEL_USER, user_area_container,'user_area_container')
        user_auth_container = HBox()
        user_auth_container.attributes.update({"editor_baseclass":"HBox","editor_tag_type":"widget","editor_newclass":"False","editor_constructor":"()","class":"HBox","editor_varname":"user_auth_container"})
        user_auth_container.style.update({"right":"1px","align-items":"center","visibility":"visible","height":"35px","overflow":"auto","top":"1px","flex-direction":"row","width":"300px","justify-content":"space-around","position":"absolute","margin":"0px","display":"flex"})
        bt_user_login = Button('login')
        bt_user_login.attributes.update({"editor_baseclass":"Button","editor_tag_type":"widget","editor_newclass":"False","editor_constructor":"('login')","class":"Button","editor_varname":"bt_user_login"})
        bt_user_login.style.update({"width":"100px","position":"static","top":"20px","order":"2","margin":"0px","overflow":"auto","height":"30px"})
        bt_user_login.onclick.do(self.on_prompt_login)
        self.bt_user_login = bt_user_login
        user_auth_container.append(bt_user_login,'bt_user_login')
        user_name = Label('not logged in')
        user_name.attributes.update({"editor_baseclass":"Label","editor_tag_type":"widget","editor_newclass":"False","editor_constructor":"('not logged in')","class":"Label","editor_varname":"user_name"})
        user_name.style.update({"width":"100px","font-weight":"bold","position":"static","top":"20px","order":"1","margin":"0px","overflow":"auto","height":"30px"})
        self.user_name = user_name
        user_auth_container.append(user_name,'user_name')
        bt_user_logout = Button('logout')
        bt_user_logout.attributes.update({"editor_baseclass":"Button","editor_tag_type":"widget","editor_newclass":"False","editor_constructor":"('logout')","class":"Button","editor_varname":"bt_user_logout"})
        bt_user_logout.style.update({"visibility":"visible","height":"30px","overflow":"auto","top":"20px","order":"3","width":"100px","position":"static","margin":"0px","display":"none","background-color":"#fa3200"})
        bt_user_logout.onclick.do(self.on_logout)
        self.bt_user_logout = bt_user_logout
        user_auth_container.append(bt_user_logout,'bt_user_logout')
        main_container.append(user_auth_container,'user_auth_container')
        admin_area_container = Container()
        admin_area_container.attributes.update({"editor_baseclass":"Container","editor_tag_type":"widget","editor_newclass":"False","editor_constructor":"()","class":"Container","editor_varname":"admin_area_container"})
        admin_area_container.style.update({"border-color":"#030303","height":"440.0px","border-style":"dotted","overflow":"auto","top":"40.0px","border-width":"1px","width":"260.0px","position":"absolute","margin":"0px","left":"300.0px"})
        lbl_admin_panel = Label('Administration panel')
        lbl_admin_panel.attributes.update({"editor_baseclass":"Label","editor_tag_type":"widget","editor_newclass":"False","editor_constructor":"('Administration panel')","class":"Label","editor_varname":"lbl_admin_panel"})
        lbl_admin_panel.style.update({"width":"158px","position":"absolute","top":"20.0px","left":"20.0px","margin":"0px","overflow":"auto","height":"27px"})
        admin_area_container.append(lbl_admin_panel,'lbl_admin_panel')
        #main_container.append(admin_area_container,'admin_area_container')
        self.container_proxy.append(User.USER_LEVEL_ADMIN, admin_area_container,'admin_area_container')

        example_users = {}
        example_users['admin'] = User('admin', 'pwdadmin', User.USER_LEVEL_ADMIN)
        example_users['user'] = User('user', 'pwduser', User.USER_LEVEL_USER)
        self.login_manager = LoginManager(example_users, CookieInterface(self), 60*60) #autologout 1 hour (60 seconds x 60 minutes)
        self.login_manager.on_session_expired.do(self.on_logout)

        self.main_container = main_container
        self.on_logout(None)
        return self.main_container

    def on_prompt_login(self, emitter):
        self.login_dialog = gui.GenericDialog("Login", "Type here login data", width=300)
        username_input = gui.TextInput(width=250)
        password_input = gui.TextInput(width=250)
        self.login_dialog.add_field_with_label('username', 'Username', username_input)
        self.login_dialog.add_field_with_label('password', 'Password', password_input)
        self.login_dialog.confirm_dialog.do(self.on_login_confirm)
        self.login_dialog.show(self)

    def on_login_confirm(self, emitter):
        username = self.login_dialog.get_field('username').get_value()
        password = self.login_dialog.get_field('password').get_value()
        user = self.login_manager.login(username, password)
        if user != None:
            print("logged in")
            self.user_name.set_text("hello " + user.username)
            self.bt_user_login.style['display'] = 'none'
            self.bt_user_logout.style['display'] = 'inline'
            self.container_proxy.set_logged_user_level(user.user_level)

    def on_renew(self, emitter):
        #THIS METHOD HAVE TO BE CALLED EACH TIME A USER DOES SOMETHING ON THE INTERFACE
        # IT IS TO SAY EACH "INTERACTION" to keep the access alive, otherwise the user will be disconnected after a timeout
        #if the user is still logged in
        if not self.login_manager.user_logged_instance is None:
            self.login_manager.renew_session()
        else:
            self.on_logout(None)

    def on_logout(self, emitter):
        self.bt_user_login.style['display'] = 'inline'
        self.bt_user_logout.style['display'] = 'none'
        self.user_name.set_text("not logged in")
        self.container_proxy.set_logged_user_level()


if __name__ == "__main__":
    # starts the webserver
    start(MyApp, address='0.0.0.0', port=0, multiple_instance=False, debug=False)

from remi.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.