Skip to content

Commit 62558d6

Browse files
Merge pull request #21 from ashirrwad/fpm-security
Added support for stdlib and fpm
2 parents 4b67df5 + 50d125b commit 62558d6

File tree

9 files changed

+133
-40
lines changed

9 files changed

+133
-40
lines changed

Backend/Docker/Dockerfile

+17-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,23 @@ FROM alpine:latest
55
RUN apk add --no-cache bash bash-doc bash-completion
66
RUN apk add --no-cache musl-dev
77
RUN apk add --no-cache gfortran
8+
RUN apk add git
9+
RUN apk add wget
810

9-
#Assigning default directory
1011
WORKDIR /fortran
12+
#Fetching FPM from releases
13+
RUN wget https://github.com/fortran-lang/fpm/releases/download/v0.6.0/fpm-0.6.0-linux-x86_64 -4
14+
RUN mv fpm-0.6.0-linux-x86_64 fpm
15+
#Setup for FPM
16+
RUN chmod u+x fpm
17+
RUN mkdir playground
18+
RUN mkdir playground/app
19+
RUN mkdir playground/libraries
1120

21+
#Fetching libraries
22+
WORKDIR /fortran/playground/libraries
23+
#Setting up stdlib
24+
RUN git clone https://github.com/fortran-lang/stdlib.git
25+
WORKDIR /fortran/playground/libraries/stdlib
26+
RUN git checkout stdlib-fpm
27+
WORKDIR /fortran/playground

Backend/File.f90

-3
This file was deleted.

Backend/Pipfile

+1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ flask = "*"
88
docker = "*"
99
flask-cors = "*"
1010
pyyaml = "*"
11+
tomlkit = "*"
1112

1213
[dev-packages]

Backend/app.py

+28-26
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import tarfile
77
import yaml
88
import json
9+
import tomlkit
10+
911
app = Flask(__name__)
1012

1113
cors = CORS(app)
@@ -14,7 +16,7 @@
1416

1517
# Starting container
1618
client = docker.from_env()
17-
container = client.containers.run("playground-small", tty=True, detach=True, network_disabled=True, mem_limit="16g")
19+
container = client.containers.run("playground-f", tty=True, detach=True, network_disabled=True, mem_limit="16g")
1820

1921
#Converting tutorial YAML
2022
with open('tutorial.yml', 'r') as file:
@@ -25,13 +27,22 @@
2527

2628

2729
# Editing the file with code inside editor
28-
def edit_file(code, input=""):
29-
Fortran_file = open("./File.f90", "w+")
30+
def edit_file(code, input, libs):
31+
Fortran_file = open("./main.f90", "w+") #main source code from editor
3032
Fortran_file.write(code)
3133
Fortran_file.close()
32-
program_input = open("./program_input.txt", "w+")
34+
program_input = open("./program_input.txt", "w+") #user input
3335
program_input.write(input)
3436
program_input.close()
37+
#Generating fpm.toml for fpm processing
38+
with open("fpm.toml", mode="rt", encoding="utf-8") as fp:
39+
fpm = tomlkit.load(fp)
40+
if "stdlib" in libs:
41+
fpm["dependencies"] = {'stdlib' : {'path' : "libraries/stdlib"}}
42+
else:
43+
fpm["dependencies"] = {}
44+
with open("fpm.toml", mode="wt", encoding="utf-8") as fp:
45+
tomlkit.dump(fpm, fp)
3546

3647
# Copying file with fortran code to container
3748
def copy_to(src, dst, container):
@@ -52,17 +63,12 @@ def copy_to(src, dst, container):
5263

5364
# Executing code inside container and getting it's output
5465
def execute_code_in_container():
55-
copy_to("./File.f90", "/fortran/File.f90", container)
56-
copy_to("./program_input.txt", "/fortran/program_input.txt", container)
57-
executable = container.exec_run(
58-
"gfortran File.f90 -o executed_file.o", demux=True
59-
)
60-
if executable.exit_code == 0:
61-
a = container.exec_run(
62-
'sh -c "cat program_input.txt | timeout 15s ./executed_file.o"', demux=True
63-
)
64-
else:
65-
a = executable
66+
copy_to('./main.f90', '/fortran/playground/app/main.f90', container)
67+
copy_to('./program_input.txt', '/fortran/playground/program_input.txt', container)
68+
copy_to('./fpm.toml','/fortran/playground/fpm.toml', container)
69+
container.exec_run('sh -c "/fortran/fpm build"')
70+
a = container.exec_run('sh -c "cat program_input.txt | timeout 15s /fortran/fpm run"',demux=True)
71+
6672
return a
6773

6874

@@ -71,18 +77,14 @@ def execute_code_in_container():
7177
@cross_origin()
7278
def run_code():
7379
data = request.get_json()
74-
edit_file(data["code"], data["programInput"])
80+
edit_file(data["code"], data["programInput"], data["libs"])
7581
code_result = execute_code_in_container()
76-
if code_result.exit_code == 0:
77-
if code_result.output[0] == None:
78-
output = jsonify({"executed": ""})
79-
return output, 202
80-
81-
print(code_result.output[0].decode())
82-
output = jsonify({"executed": code_result.output[0].decode()})
83-
else:
84-
print(code_result.output[1].decode())
85-
output = jsonify({"executed": code_result.output[1].decode()})
82+
if code_result.output[0] == None:
83+
output = jsonify({"executed": ""})
84+
return output, 202
85+
output = jsonify({"executed": code_result.output[0].decode()})
86+
print(code_result.output)
87+
8688

8789
return output, 202
8890

Backend/fpm.toml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name = "playground"
2+
author = "Ashirwad Mishra"
3+
maintainer = "[email protected]"
4+
5+
[build]
6+
auto-executables = true
7+
auto-tests = true
8+
auto-examples = true
9+
10+
[install]
11+
library = false
12+
13+
[dependencies]

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ An interactive Fortran playground
66
# Flask API
77
1. Install Docker
88
2. Build docker image (Switch to docker directory)
9-
``` docker build -t playground-small .```
9+
``` docker build -t playground-f .```
1010
3. Install pipenv to manage packages
1111
```pip install pipenv```
1212
4. Switch to backend directory and

frontend/src/App.css

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
padding: 0.2rem;
1313
display: flex;
1414
flex-direction: column;
15-
justify-content: space-between;
15+
justify-content: space-around;
1616

1717
}
1818

frontend/src/App.js

+71-7
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,44 @@ import RunCode from './run.png'
1212
import ResetCode from './reset.png'
1313
import InputBox from './InputBox';
1414
import TutorialCard from './TutorialCard';
15+
import Modal from 'react-bootstrap/Modal';
16+
import Form from 'react-bootstrap/Form';
17+
1518

1619
function NewlineText(props) {
1720
const text = props.text;
1821
return <div className='output-formmating'>{text}</div>;
1922
}
2023

24+
var libs = []
2125

2226
function App() {
2327
const [ text, setText ] = useState('') //State to store editor code
2428
const [output, setOutput] = useState('')//State to store output
2529
const [isLoading, setIsLoading] = useState(false);//Loading animations
26-
const [ input, setInput ] = useState('')
27-
const [inputOn, setinputOn] = useState(false)
30+
const [ input, setInput ] = useState('') // user input
31+
const [inputOn, setinputOn] = useState(false) // toggle for input button
32+
const [show, setShow] = useState(false); // library modal toggle
33+
const handleClose = () => setShow(false);
34+
const handleShow = () => setShow(true);
35+
const [stdlibOn, setstdlibOn] = useState(false); // state to store package info
36+
37+
{/*switch toggle for stdlib */}
38+
const onSwitchAction = () => {
39+
setstdlibOn(!stdlibOn);
40+
if(!stdlibOn){
41+
libs.push("stdlib")
42+
}
43+
else{
44+
if(libs.includes("stdlib")){
45+
libs = libs.filter(item => item !== "stdlib")
46+
47+
}
48+
}
49+
50+
};
51+
52+
2853

2954

3055
const handleInputChange = (e) => {
@@ -33,6 +58,7 @@ function App() {
3358
console.log(input)
3459
};
3560

61+
//inputbox toggle
3662
const handleInputBox = (e) =>{
3763
{inputOn ? setinputOn(false) : setinputOn(true)}
3864
//setinputOn(true)
@@ -43,11 +69,12 @@ function App() {
4369
setOutput('')
4470
setIsLoading(true);
4571
// POST request using axios inside useEffect React hook
46-
await axios.post('http://127.0.0.1:5000/run', {code : text, programInput: input})
72+
await axios.post('http://127.0.0.1:5000/run', {code : text, programInput: input, libs: libs})
4773
.then((response) => {setOutput(response.data.executed)});
4874
setIsLoading(false);
4975
}
5076

77+
//reset code button
5178
const resetCode = () => {
5279
setText("")
5380
}
@@ -77,6 +104,10 @@ function App() {
77104
background-color: #009900;
78105
color: white;
79106
}
107+
.btn-run:focus{
108+
background-color: #734f96;
109+
color: white;
110+
}
80111
`}
81112
</style>
82113

@@ -98,12 +129,45 @@ function App() {
98129
</Card.Body>
99130
</Card>
100131

132+
133+
{/*Tutorial Card Component */}
101134
<TutorialCard />
102135
{/* Input Box to provide input for program */}
103-
{/*<InputBox value={input} onChange={handleInputChange}/> */}
104-
<Button onClick={handleInputBox}>INPUT</Button>
105-
{inputOn ? <InputBox value={input} onChange={handleInputChange}/> : null}
106-
136+
<div>
137+
<Button onClick={handleInputBox}>Input</Button>
138+
{inputOn ? <InputBox value={input} onChange={handleInputChange}/> : null} {/*toggle for input */}
139+
140+
141+
<Button variant="primary" onClick={handleShow}>
142+
Libraries
143+
</Button>
144+
{/*Library selector pop-up modal */}
145+
<Modal show={show} onHide={handleClose}>
146+
<Modal.Header closeButton>
147+
<Modal.Title>Packages</Modal.Title>
148+
</Modal.Header>
149+
<Modal.Body>Please select the packages you want
150+
<Form>
151+
<Form.Check
152+
type="switch"
153+
id="custom-switch"
154+
label="stdlib"
155+
onChange={onSwitchAction}
156+
checked={stdlibOn}
157+
/>
158+
</Form>
159+
</Modal.Body>
160+
<Modal.Footer>
161+
<Button variant="secondary" onClick={handleClose}>
162+
Close
163+
</Button>
164+
<Button variant="primary" onClick={handleClose}>
165+
Save Changes
166+
</Button>
167+
</Modal.Footer>
168+
</Modal>
169+
</div>
170+
107171
</div>
108172

109173
</div>

frontend/src/TutorialCard.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function TutorialCard(props) {
2525
}
2626
}
2727
return (
28-
<Card style={{ width: '100%', height: '100%' }} className="overflow-auto">
28+
<Card style={{ width: '100%', height: '50%' }} className="overflow-auto">
2929

3030
<Card.Body>
3131
<Card.Title>{Tutorial[exercise].title}</Card.Title>

0 commit comments

Comments
 (0)