ivoryos 0.1.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ivoryos might be problematic. Click here for more details.
- ivoryos-0.1.5/LICENSE +21 -0
- ivoryos-0.1.5/MANIFEST.in +8 -0
- ivoryos-0.1.5/PKG-INFO +96 -0
- ivoryos-0.1.5/README.md +77 -0
- ivoryos-0.1.5/ivoryos/__init__.py +94 -0
- ivoryos-0.1.5/ivoryos/config.py +46 -0
- ivoryos-0.1.5/ivoryos/routes/__init__.py +0 -0
- ivoryos-0.1.5/ivoryos/routes/auth/__init__.py +0 -0
- ivoryos-0.1.5/ivoryos/routes/auth/auth.py +65 -0
- ivoryos-0.1.5/ivoryos/routes/auth/templates/auth/login.html +25 -0
- ivoryos-0.1.5/ivoryos/routes/auth/templates/auth/signup.html +32 -0
- ivoryos-0.1.5/ivoryos/routes/control/__init__.py +0 -0
- ivoryos-0.1.5/ivoryos/routes/control/control.py +233 -0
- ivoryos-0.1.5/ivoryos/routes/control/templates/control/controllers.html +71 -0
- ivoryos-0.1.5/ivoryos/routes/control/templates/control/controllers_home.html +50 -0
- ivoryos-0.1.5/ivoryos/routes/control/templates/control/controllers_new.html +89 -0
- ivoryos-0.1.5/ivoryos/routes/database/__init__.py +0 -0
- ivoryos-0.1.5/ivoryos/routes/database/database.py +122 -0
- ivoryos-0.1.5/ivoryos/routes/database/templates/database/experiment_database.html +72 -0
- ivoryos-0.1.5/ivoryos/routes/design/__init__.py +0 -0
- ivoryos-0.1.5/ivoryos/routes/design/design.py +396 -0
- ivoryos-0.1.5/ivoryos/routes/design/templates/design/experiment_builder.html +413 -0
- ivoryos-0.1.5/ivoryos/routes/design/templates/design/experiment_run.html +325 -0
- ivoryos-0.1.5/ivoryos/routes/main/__init__.py +0 -0
- ivoryos-0.1.5/ivoryos/routes/main/main.py +25 -0
- ivoryos-0.1.5/ivoryos/routes/main/templates/main/help.html +144 -0
- ivoryos-0.1.5/ivoryos/routes/main/templates/main/home.html +68 -0
- ivoryos-0.1.5/ivoryos/static/favicon.ico +0 -0
- ivoryos-0.1.5/ivoryos/static/gui_annotation/Slide1.png +0 -0
- ivoryos-0.1.5/ivoryos/static/gui_annotation/Slide2.PNG +0 -0
- ivoryos-0.1.5/ivoryos/static/js/overlay.js +12 -0
- ivoryos-0.1.5/ivoryos/static/js/socket_handler.js +25 -0
- ivoryos-0.1.5/ivoryos/static/js/sortable_card.js +24 -0
- ivoryos-0.1.5/ivoryos/static/js/sortable_design.js +36 -0
- ivoryos-0.1.5/ivoryos/static/logo.png +0 -0
- ivoryos-0.1.5/ivoryos/static/style.css +202 -0
- ivoryos-0.1.5/ivoryos/templates/base.html +141 -0
- ivoryos-0.1.5/ivoryos/utils/__init__.py +0 -0
- ivoryos-0.1.5/ivoryos/utils/db_models.py +501 -0
- ivoryos-0.1.5/ivoryos/utils/form.py +316 -0
- ivoryos-0.1.5/ivoryos/utils/global_config.py +68 -0
- ivoryos-0.1.5/ivoryos/utils/llm_agent.py +183 -0
- ivoryos-0.1.5/ivoryos/utils/script_runner.py +158 -0
- ivoryos-0.1.5/ivoryos/utils/task_manager.py +80 -0
- ivoryos-0.1.5/ivoryos/utils/utils.py +337 -0
- ivoryos-0.1.5/ivoryos.egg-info/PKG-INFO +96 -0
- ivoryos-0.1.5/ivoryos.egg-info/SOURCES.txt +50 -0
- ivoryos-0.1.5/ivoryos.egg-info/dependency_links.txt +1 -0
- ivoryos-0.1.5/ivoryos.egg-info/requires.txt +8 -0
- ivoryos-0.1.5/ivoryos.egg-info/top_level.txt +1 -0
- ivoryos-0.1.5/setup.cfg +4 -0
- ivoryos-0.1.5/setup.py +27 -0
ivoryos-0.1.5/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023-2024 Ivory Zhang | Hein Lab
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
ivoryos-0.1.5/PKG-INFO
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: ivoryos
|
|
3
|
+
Version: 0.1.5
|
|
4
|
+
Summary: an open-source Python package enabling Self-Driving Labs (SDLs) interoperability
|
|
5
|
+
Home-page: https://gitlab.com/heingroup/ivoryos
|
|
6
|
+
Author: Ivory Zhang
|
|
7
|
+
Author-email: ivoryzhang@chem.ubc.ca
|
|
8
|
+
License: MIT
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Requires-Dist: bcrypt
|
|
12
|
+
Requires-Dist: Flask-Login
|
|
13
|
+
Requires-Dist: Flask-Session
|
|
14
|
+
Requires-Dist: Flask-SocketIO
|
|
15
|
+
Requires-Dist: Flask-SQLAlchemy
|
|
16
|
+
Requires-Dist: Flask-WTF
|
|
17
|
+
Requires-Dist: SQLAlchemy-Utils
|
|
18
|
+
Requires-Dist: python-dotenv
|
|
19
|
+
|
|
20
|
+

|
|
21
|
+
# ivoryOS: interoperable Web UI for self-driving laboratories (SDLs)
|
|
22
|
+
ivoryOS is a "plug and play" web UI extension for flexible SDLs, enabling interoperability between SDLs.
|
|
23
|
+
## Description
|
|
24
|
+
Granting SDLs flexibility and modularity makes it almost impossible to design a UI, yet it's a necessity for allowing more people to interact with it (democratisation).
|
|
25
|
+
This web UI aims to ease up the control of any Python-based SDLs by displaying functions and parameters for initialized modules dynamically.
|
|
26
|
+
The modules can be hardware API, high-level functions, or experiment workflow.
|
|
27
|
+
With the least modification of the current workflow, user can design, manage and execute their experimental designs and monitor the execution process.
|
|
28
|
+
## AI assistant
|
|
29
|
+
To streamline the experimental design on SDLs, we also integrate Large Language Models (LLMs) to interpret the inspected functions and generate code according to task descriptions.
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
```
|
|
33
|
+
pip install ivoryos
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
### Quick start
|
|
38
|
+
In your SDL script, use `ivoryos(__name__)`. Example in [abstract_sdl.py](https://gitlab.com/heingroup/ivoryos/-/blob/main/example/dummy_ur/dummy_deck.py)
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
import ivoryos
|
|
42
|
+
|
|
43
|
+
ivoryos.run(__name__)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Additional settings
|
|
47
|
+
#### Enable LLMs with [OpenAI API](https://github.com/openai/openai-python)
|
|
48
|
+
1. Create a `.env` file for `OPENAI_API_KEY`
|
|
49
|
+
```
|
|
50
|
+
OPENAI_API_KEY="Your API Key"
|
|
51
|
+
```
|
|
52
|
+
2. In your SDL script, define model, you can use any GPT models.
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
ivoryos.run(__name__, model="gpt-3.5-turbo")
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
#### Enable local LLMs with [Ollama](https://ollama.com/)
|
|
59
|
+
1. Download Ollama.
|
|
60
|
+
2. pull models from Ollama
|
|
61
|
+
3. In your SDL script, define LLM server and model, you can use any models available on Ollama.
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
ivoryos.run(__name__, llm_server="localhost", model="llama3.1")
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
#### Add additional logger(s)
|
|
68
|
+
```python
|
|
69
|
+
ivoryos.run(__name__, logger="logger name")
|
|
70
|
+
```
|
|
71
|
+
or
|
|
72
|
+
```python
|
|
73
|
+
ivoryos.run(__name__, logger=["logger 1", "logger 2"])
|
|
74
|
+
```
|
|
75
|
+
#### Offline (design without hardware connection)
|
|
76
|
+
After one successful connection, a blueprint will be automatically saved and made accessible without hardware connection. In a new Python script in the same directory, use `ivoryos.run()` to start offline mode.
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
ivoryos.run()
|
|
80
|
+
```
|
|
81
|
+
## Deck snapshot example
|
|
82
|
+

|
|
83
|
+
## Developing
|
|
84
|
+
This is a wip project. Here are some future actions.
|
|
85
|
+
1. Support @setter decorator.
|
|
86
|
+
2. Documentation: white paper wip
|
|
87
|
+
3. Compatibility: compatability report to open-source lab hardware APIs will soon be added. As of now, due to the limitation of web form, the usability of APIs with object inputs (e.g. Opentron Python API) is very limited.
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
## Authors and Acknowledgement
|
|
91
|
+
Ivory Zhang, Lucy Hao
|
|
92
|
+
|
|
93
|
+
Authors acknowledge all former and current Hein Lab members for their valuable suggestions.
|
|
94
|
+
|
|
95
|
+
## License
|
|
96
|
+
[LICENSE](LICENSE)
|
ivoryos-0.1.5/README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+

|
|
2
|
+
# ivoryOS: interoperable Web UI for self-driving laboratories (SDLs)
|
|
3
|
+
ivoryOS is a "plug and play" web UI extension for flexible SDLs, enabling interoperability between SDLs.
|
|
4
|
+
## Description
|
|
5
|
+
Granting SDLs flexibility and modularity makes it almost impossible to design a UI, yet it's a necessity for allowing more people to interact with it (democratisation).
|
|
6
|
+
This web UI aims to ease up the control of any Python-based SDLs by displaying functions and parameters for initialized modules dynamically.
|
|
7
|
+
The modules can be hardware API, high-level functions, or experiment workflow.
|
|
8
|
+
With the least modification of the current workflow, user can design, manage and execute their experimental designs and monitor the execution process.
|
|
9
|
+
## AI assistant
|
|
10
|
+
To streamline the experimental design on SDLs, we also integrate Large Language Models (LLMs) to interpret the inspected functions and generate code according to task descriptions.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
```
|
|
14
|
+
pip install ivoryos
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
### Quick start
|
|
19
|
+
In your SDL script, use `ivoryos(__name__)`. Example in [abstract_sdl.py](https://gitlab.com/heingroup/ivoryos/-/blob/main/example/dummy_ur/dummy_deck.py)
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
import ivoryos
|
|
23
|
+
|
|
24
|
+
ivoryos.run(__name__)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Additional settings
|
|
28
|
+
#### Enable LLMs with [OpenAI API](https://github.com/openai/openai-python)
|
|
29
|
+
1. Create a `.env` file for `OPENAI_API_KEY`
|
|
30
|
+
```
|
|
31
|
+
OPENAI_API_KEY="Your API Key"
|
|
32
|
+
```
|
|
33
|
+
2. In your SDL script, define model, you can use any GPT models.
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
ivoryos.run(__name__, model="gpt-3.5-turbo")
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
#### Enable local LLMs with [Ollama](https://ollama.com/)
|
|
40
|
+
1. Download Ollama.
|
|
41
|
+
2. pull models from Ollama
|
|
42
|
+
3. In your SDL script, define LLM server and model, you can use any models available on Ollama.
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
ivoryos.run(__name__, llm_server="localhost", model="llama3.1")
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
#### Add additional logger(s)
|
|
49
|
+
```python
|
|
50
|
+
ivoryos.run(__name__, logger="logger name")
|
|
51
|
+
```
|
|
52
|
+
or
|
|
53
|
+
```python
|
|
54
|
+
ivoryos.run(__name__, logger=["logger 1", "logger 2"])
|
|
55
|
+
```
|
|
56
|
+
#### Offline (design without hardware connection)
|
|
57
|
+
After one successful connection, a blueprint will be automatically saved and made accessible without hardware connection. In a new Python script in the same directory, use `ivoryos.run()` to start offline mode.
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
ivoryos.run()
|
|
61
|
+
```
|
|
62
|
+
## Deck snapshot example
|
|
63
|
+

|
|
64
|
+
## Developing
|
|
65
|
+
This is a wip project. Here are some future actions.
|
|
66
|
+
1. Support @setter decorator.
|
|
67
|
+
2. Documentation: white paper wip
|
|
68
|
+
3. Compatibility: compatability report to open-source lab hardware APIs will soon be added. As of now, due to the limitation of web form, the usability of APIs with object inputs (e.g. Opentron Python API) is very limited.
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
## Authors and Acknowledgement
|
|
72
|
+
Ivory Zhang, Lucy Hao
|
|
73
|
+
|
|
74
|
+
Authors acknowledge all former and current Hein Lab members for their valuable suggestions.
|
|
75
|
+
|
|
76
|
+
## License
|
|
77
|
+
[LICENSE](LICENSE)
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
from typing import Union
|
|
4
|
+
|
|
5
|
+
from flask import Flask
|
|
6
|
+
|
|
7
|
+
from ivoryos.config import Config, get_config
|
|
8
|
+
from ivoryos.routes.auth.auth import auth, login_manager
|
|
9
|
+
from ivoryos.routes.control.control import control
|
|
10
|
+
from ivoryos.routes.database.database import database
|
|
11
|
+
from ivoryos.routes.design.design import design, socketio
|
|
12
|
+
from ivoryos.routes.main.main import main
|
|
13
|
+
from ivoryos.utils import utils
|
|
14
|
+
from ivoryos.utils.db_models import db
|
|
15
|
+
from ivoryos.utils.global_config import GlobalConfig
|
|
16
|
+
from ivoryos.utils.script_runner import ScriptRunner
|
|
17
|
+
|
|
18
|
+
global_config = GlobalConfig()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def create_app(config_class=None):
|
|
22
|
+
app = Flask(__name__)
|
|
23
|
+
app.config.from_object(config_class or 'config.get_config()')
|
|
24
|
+
|
|
25
|
+
# Initialize extensions
|
|
26
|
+
socketio.init_app(app)
|
|
27
|
+
login_manager.init_app(app)
|
|
28
|
+
login_manager.login_view = "auth.login"
|
|
29
|
+
db.init_app(app)
|
|
30
|
+
|
|
31
|
+
# Create database tables
|
|
32
|
+
with app.app_context():
|
|
33
|
+
db.create_all()
|
|
34
|
+
|
|
35
|
+
# Additional setup
|
|
36
|
+
utils.create_gui_dir(app.config['OUTPUT_FOLDER'])
|
|
37
|
+
|
|
38
|
+
# logger_list = app.config["LOGGERS"]
|
|
39
|
+
logger_path = os.path.join(app.config["OUTPUT_FOLDER"], app.config["LOGGERS_PATH"])
|
|
40
|
+
logger = utils.start_logger(socketio, 'gui_logger', logger_path)
|
|
41
|
+
|
|
42
|
+
@app.before_request
|
|
43
|
+
def before_request():
|
|
44
|
+
from flask import g
|
|
45
|
+
g.logger = logger
|
|
46
|
+
g.socketio = socketio
|
|
47
|
+
|
|
48
|
+
app.register_blueprint(main)
|
|
49
|
+
app.register_blueprint(auth)
|
|
50
|
+
app.register_blueprint(design)
|
|
51
|
+
app.register_blueprint(database)
|
|
52
|
+
app.register_blueprint(control)
|
|
53
|
+
|
|
54
|
+
return app
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def run(module=None, host="0.0.0.0", port=None, debug=None, llm_server=None, model=None,
|
|
58
|
+
config: Config = None,
|
|
59
|
+
logger: Union[str, list] = None,
|
|
60
|
+
logger_output_name: str = None,
|
|
61
|
+
):
|
|
62
|
+
app = create_app(config_class=config or get_config()) # Create app instance using factory function
|
|
63
|
+
|
|
64
|
+
port = port or int(os.environ.get("PORT", 8000))
|
|
65
|
+
debug = debug if debug is not None else app.config.get('DEBUG', True)
|
|
66
|
+
|
|
67
|
+
app.config["LOGGERS"] = logger
|
|
68
|
+
app.config["LOGGERS_PATH"] = logger_output_name or app.config["LOGGERS_PATH"] # default.log
|
|
69
|
+
logger_path = os.path.join(app.config["OUTPUT_FOLDER"], app.config["LOGGERS_PATH"])
|
|
70
|
+
|
|
71
|
+
if module:
|
|
72
|
+
app.config["MODULE"] = module
|
|
73
|
+
app.config["OFF_LINE"] = False
|
|
74
|
+
global_config.deck = sys.modules[module]
|
|
75
|
+
global_config.deck_variables = utils.parse_deck(global_config.deck, output_path=app.config["DUMMY_DECK"], save=True)
|
|
76
|
+
# global_config.runner = ScriptRunner(globals())
|
|
77
|
+
else:
|
|
78
|
+
app.config["OFF_LINE"] = True
|
|
79
|
+
if model:
|
|
80
|
+
app.config["ENABLE_LLM"] = True
|
|
81
|
+
app.config["LLM_MODEL"] = model
|
|
82
|
+
app.config["LLM_SERVER"] = llm_server
|
|
83
|
+
utils.install_and_import('openai')
|
|
84
|
+
from ivoryos.utils.llm_agent import LlmAgent
|
|
85
|
+
global_config.agent = LlmAgent(host=llm_server, model=model,
|
|
86
|
+
output_path=app.config["OUTPUT_FOLDER"] if module is not None else None)
|
|
87
|
+
else:
|
|
88
|
+
app.config["ENABLE_LLM"] = False
|
|
89
|
+
if logger and type(logger) is str:
|
|
90
|
+
utils.start_logger(socketio, log_filename=logger_path, logger_name=logger)
|
|
91
|
+
elif type(logger) is list:
|
|
92
|
+
for log in logger:
|
|
93
|
+
utils.start_logger(socketio, log_filename=logger_path, logger_name=log)
|
|
94
|
+
socketio.run(app, host=host, port=port, debug=debug, use_reloader=False, allow_unsafe_werkzeug=True)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from dotenv import load_dotenv
|
|
3
|
+
|
|
4
|
+
# Load environment variables from .env file
|
|
5
|
+
load_dotenv()
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Config:
|
|
9
|
+
SECRET_KEY = os.getenv('SECRET_KEY', 'default_secret_key')
|
|
10
|
+
OPENAI_API_KEY = os.getenv('OPENAI_API_KEY', None)
|
|
11
|
+
|
|
12
|
+
OUTPUT_FOLDER = os.path.join(os.path.abspath(os.curdir), 'ivoryos_data')
|
|
13
|
+
os.makedirs(OUTPUT_FOLDER, exist_ok=True)
|
|
14
|
+
CSV_FOLDER = os.path.join(OUTPUT_FOLDER, 'config_csv/')
|
|
15
|
+
SCRIPT_FOLDER = os.path.join(OUTPUT_FOLDER, 'scripts/')
|
|
16
|
+
DATA_FOLDER = os.path.join(OUTPUT_FOLDER, 'results/')
|
|
17
|
+
DUMMY_DECK = os.path.join(OUTPUT_FOLDER, 'pseudo_deck/')
|
|
18
|
+
DECK_HISTORY = os.path.join(OUTPUT_FOLDER, 'deck_history.txt')
|
|
19
|
+
LOGGERS_PATH = "default.log"
|
|
20
|
+
|
|
21
|
+
SQLALCHEMY_DATABASE_URI = f"sqlite:///{os.path.join(OUTPUT_FOLDER, 'ivoryos.db')}"
|
|
22
|
+
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
|
23
|
+
|
|
24
|
+
ENABLE_LLM = True if OPENAI_API_KEY else False
|
|
25
|
+
OFF_LINE = True
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class DevelopmentConfig(Config):
|
|
29
|
+
DEBUG = True
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ProductionConfig(Config):
|
|
33
|
+
DEBUG = False
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class TestingConfig(Config):
|
|
37
|
+
DEBUG = True
|
|
38
|
+
TESTING = True
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def get_config(env='dev'):
|
|
42
|
+
if env == 'production':
|
|
43
|
+
return ProductionConfig()
|
|
44
|
+
elif env == 'testing':
|
|
45
|
+
return TestingConfig()
|
|
46
|
+
return DevelopmentConfig()
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from flask import Blueprint, redirect, url_for, flash, request, render_template, session
|
|
2
|
+
from flask_login import login_required, login_user, logout_user, LoginManager
|
|
3
|
+
import bcrypt
|
|
4
|
+
|
|
5
|
+
from ivoryos.utils.db_models import Script, User, db
|
|
6
|
+
from ivoryos.utils.utils import post_script_file
|
|
7
|
+
login_manager = LoginManager()
|
|
8
|
+
|
|
9
|
+
auth = Blueprint('auth', __name__, template_folder='templates/auth')
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@auth.route('/login', methods=['GET', 'POST'])
|
|
13
|
+
def login():
|
|
14
|
+
if request.method == 'POST':
|
|
15
|
+
username = request.form.get('username')
|
|
16
|
+
password = request.form.get('password')
|
|
17
|
+
|
|
18
|
+
# session.query(User, User.name).all()
|
|
19
|
+
user = db.session.query(User).filter(User.username == username).first()
|
|
20
|
+
input_password = password.encode('utf-8')
|
|
21
|
+
# if user and bcrypt.checkpw(input_password, user.hashPassword.encode('utf-8')):
|
|
22
|
+
if user and bcrypt.checkpw(input_password, user.hashPassword):
|
|
23
|
+
# password.encode("utf-8")
|
|
24
|
+
# user = User(username, password.encode("utf-8"))
|
|
25
|
+
login_user(user)
|
|
26
|
+
session['user'] = username
|
|
27
|
+
script_file = Script(author=username)
|
|
28
|
+
session["script"] = script_file.as_dict()
|
|
29
|
+
session['hidden_functions'], session['card_order'], session['prompt'] = {}, {}, {}
|
|
30
|
+
session['autofill'] = False
|
|
31
|
+
post_script_file(script_file)
|
|
32
|
+
return redirect(url_for('main.index'))
|
|
33
|
+
else:
|
|
34
|
+
flash("Incorrect username or password")
|
|
35
|
+
return render_template('login.html')
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@auth.route('/signup', methods=['GET', 'POST'])
|
|
39
|
+
def signup():
|
|
40
|
+
if request.method == 'POST':
|
|
41
|
+
username = request.form.get('username')
|
|
42
|
+
password = request.form.get('password')
|
|
43
|
+
salt = bcrypt.gensalt()
|
|
44
|
+
hashed = bcrypt.hashpw(password.encode('utf-8'), salt)
|
|
45
|
+
user = User(username, hashed)
|
|
46
|
+
try:
|
|
47
|
+
db.session.add(user)
|
|
48
|
+
db.session.commit()
|
|
49
|
+
return redirect(url_for('auth.login'))
|
|
50
|
+
except Exception:
|
|
51
|
+
flash("username exists :(")
|
|
52
|
+
return render_template('signup.html')
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@auth.route("/logout")
|
|
56
|
+
@login_required
|
|
57
|
+
def logout():
|
|
58
|
+
logout_user()
|
|
59
|
+
session.clear()
|
|
60
|
+
return redirect(url_for('auth.login'))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@login_manager.user_loader
|
|
64
|
+
def load_user(username):
|
|
65
|
+
return User(username, password=None)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{% extends 'base.html' %}
|
|
2
|
+
{% block title %}IvoryOS | Login{% endblock %}
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
{% block body %}
|
|
6
|
+
<div class= "login">
|
|
7
|
+
<div class="bg-white rounded shadow-sm flex-fill">
|
|
8
|
+
<div class="p-4" style="align-items: center">
|
|
9
|
+
<h5>Log in</h5>
|
|
10
|
+
<form role="form" method='POST' name="login" action="{{ url_for('auth.login') }}">
|
|
11
|
+
<div class="input-group mb-3">
|
|
12
|
+
<label class="input-group-text" for="username">Username</label>
|
|
13
|
+
<input class="form-control" type="text" id="username" name="username">
|
|
14
|
+
</div>
|
|
15
|
+
<div class="input-group mb-3">
|
|
16
|
+
<label class="input-group-text" for="password">Password</label>
|
|
17
|
+
<input class="form-control" type="password" id="password" name="password">
|
|
18
|
+
</div>
|
|
19
|
+
<button type="submit" class="btn btn-secondary" name="login" style="width: 100%;">login</button>
|
|
20
|
+
</form>
|
|
21
|
+
<p class="message">Not registered? <a href="{{ url_for('auth.signup') }}">Create a new account</a>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
{% endblock %}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{% extends 'base.html' %}
|
|
2
|
+
{% block title %}IvoryOS | Signup{% endblock %}
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
{% block body %}
|
|
6
|
+
<div class= "login">
|
|
7
|
+
<div class="bg-white rounded shadow-sm flex-fill">
|
|
8
|
+
<div class="p-4" style="align: center">
|
|
9
|
+
<h5>Create a new account</h5>
|
|
10
|
+
<form role="form" method='POST' name="signup" action="{{ url_for('auth.signup') }}">
|
|
11
|
+
|
|
12
|
+
<div class="input-group mb-3">
|
|
13
|
+
<label class="input-group-text" for="username">Username</label>
|
|
14
|
+
<input class="form-control" type="text" id="username" name="username" required>
|
|
15
|
+
</div>
|
|
16
|
+
<div class="input-group mb-3">
|
|
17
|
+
<label class="input-group-text" for="password">Password</label>
|
|
18
|
+
<input class="form-control" type="password" id="password" name="password" required>
|
|
19
|
+
</div>
|
|
20
|
+
{# <div class="input-group mb-3">#}
|
|
21
|
+
{# <label class="input-group-text" for="confirm_password">Confirm Password</label>#}
|
|
22
|
+
{# <input class="form-control" type="confirm_password" id="confirm_password" name="confirm_password">#}
|
|
23
|
+
{# </div>#}
|
|
24
|
+
|
|
25
|
+
<button type="submit" class="btn btn-secondary" name="login" style="width: 100%;">Sign up</button>
|
|
26
|
+
</form>
|
|
27
|
+
<p class="message" >Already registered? <a href="{{ url_for('auth.login') }}">Sign In</a></p>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
{% endblock %}
|
|
File without changes
|