Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b8cae2b
chat-widget
vickeykumar May 19, 2024
ad34ced
16 bit small secret for PID
vickeykumar May 19, 2024
240fe4c
handle click outside util
vickeykumar May 19, 2024
c1a0548
chat-widget peerchat
vickeykumar May 19, 2024
bca33b4
chat-widget peerchat save history
vickeykumar May 19, 2024
473f494
chat-widget uuid for each peer user
vickeykumar May 19, 2024
3e8415c
logo update
vickeykumar May 19, 2024
6c97be0
logo changes
vickeykumar May 25, 2024
ca00802
tmp go cache
vickeykumar May 27, 2024
0695c31
chat-widget: submit on keydown
vickeykumar Jun 13, 2024
5c947c6
moved share-buttons to footer
vickeykumar Jun 15, 2024
2e99c25
share button height
vickeykumar Jun 15, 2024
8ff02c7
removed beta
vickeykumar Jun 15, 2024
7fad387
removed editors dependency on firebase for init
vickeykumar Jun 16, 2024
91c95bc
install rust
vickeykumar Jun 16, 2024
ee5fc32
installed rust repl
vickeykumar Jun 16, 2024
062acfc
imporved doc
vickeykumar Jun 16, 2024
96935ed
inc size limit of docker image
vickeykumar Jun 17, 2024
72ec391
sqlite
vickeykumar Jun 17, 2024
5d4c52f
typescript repl
vickeykumar Jun 17, 2024
ac5de88
tsc version test
vickeykumar Jun 17, 2024
c62a267
vertical and horizontal split of ide/terminal at runtime
vickeykumar Jun 20, 2024
859347f
some more theme specific changes
vickeykumar Jun 20, 2024
857352e
vertical ratio updated
vickeykumar Jun 20, 2024
a869662
token expiry message updated
vickeykumar Jun 27, 2024
bc66725
chatgpt to genie
vickeykumar Jun 27, 2024
fd78df8
chatgpt to genie 2
vickeykumar Jun 28, 2024
58f8c55
chatgpt to genie 3
vickeykumar Jun 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/docker-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,7 @@ jobs:
uses: wemake-services/docker-image-size-limit@master
with: # lint this image by itself
image: 'openrepl:latest'
size: 2048MB
size: 3GB
max_layers: 15
show_current_size: true
exit_zero: true
77 changes: 63 additions & 14 deletions install_prerequisite.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@

GOTTY_DIR=/opt/gotty
mkdir -p $GOTTY_DIR || true
chmod -R 644 $GOTTY_DIR
chmod 644 $GOTTY_DIR
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
echo "running script from : " $SCRIPT_DIR

retVal=0

Expand All @@ -16,24 +15,38 @@ display_usage() {
echo " --cleanup-tools Cleanup tools after REPLs installation"
echo " --run-tests Run tests"
echo " --help Display this help message"
echo " --username USERNAME Specify the username for installation"
}

cleanup_tools=0
run_tests=0

for arg in "$@"; do
case $arg in
--cleanup-tools) cleanup_tools=1
;;
--run-tests) run_tests=1
;;
--help) display_usage; exit 0
;;
*) echo "Invalid argument: $arg"; display_usage; exit 1
;;
username=$(whoami)

# Parse command-line arguments
while [[ "$#" -gt 0 ]]; do
case $1 in
--cleanup-tools) cleanup_tools=1; shift ;;
--run-tests) run_tests=1; shift ;;
--help) display_usage; exit 0 ;;
--username)
if [[ -n "$2" && "$2" != --* ]]; then
username="$2"; shift 2
else
echo "Error: --username requires a value"
display_usage
exit 1
fi
;;
*)
echo "Invalid argument: $1"
display_usage
exit 1
;;
esac
done

echo "running script from : " $SCRIPT_DIR
echo "username: " $username

cd ~

Expand Down Expand Up @@ -95,7 +108,7 @@ npm install npm@8.5.1 -g
#/usr/bin/cling 21321 .q > /dev/null 2>&1 &
cd $GOTTY_DIR

if [[ -e "/usr/local/bin/cling" ]]; then
if [ -e "/usr/local/bin/cling" ]; then
echo "File /usr/local/bin/cling exists."
else
echo "File /usr/local/bin/cling does not exist. installing..."
Expand All @@ -107,6 +120,24 @@ else
rm cling-Ubuntu-22.04-x86_64-1.0~dev-d47b49c.tar.bz2
fi

#install evcxr and set all the required dependencies
if [ -e "/usr/local/bin/evcxr" ]; then
echo "File /usr/local/bin/evcxr exists."
else
echo "File /usr/local/bin/evcxr does not exist. installing..."
apt-get install -y --no-install-recommends rustc
apt-get install -y --no-install-recommends rust-gdb
apt-get install -y --no-install-recommends cargo
#evcxr install
wget https://github.com/evcxr/evcxr/releases/download/v0.17.0/evcxr-v0.17.0-x86_64-unknown-linux-gnu.tar.gz
tar -xvf evcxr-v0.17.0-x86_64-unknown-linux-gnu.tar.gz
cp evcxr-v0.17.0-x86_64-unknown-linux-gnu/evcxr /usr/local/bin/evcxr
chmod 755 /usr/local/bin/evcxr
rm evcxr-v0.17.0-x86_64-unknown-linux-gnu.tar.gz
rm -rf evcxr-v0.17.0-x86_64-unknown-linux-gnu
fi



#install gointerpreter
git clone https://github.com/vickeykumar/Go-interpreter.git
Expand Down Expand Up @@ -138,6 +169,14 @@ cd ~
#install tcl
apt-get install -y --no-install-recommends tcl

#install sqlite3
apt-get install -y --no-install-recommends sqlite3

#install typescript and ts-node
npm install -g typescript@4.9.5
npm install -g ts-node
npm link typescript

# Docker: Error response from daemon: cgroups: cgroup mountpoint does not exist: unknown
# if using docker use privileged mode with cgroup mounted (-v /sys/fs/cgroup:/sys/fs/cgroup:rw )
mkdir /sys/fs/cgroup/systemd || true
Expand Down Expand Up @@ -165,6 +204,10 @@ if [ $cleanup_tools -eq 1 ]; then
apt-get -y autoremove
fi

# finally give the ownership to username
chown -R $username:$username $GOTTY_DIR
chmod -R 755 $GOTTY_DIR

#test
if [ $run_tests -eq 1 ]; then
test_commands=(
Expand All @@ -187,6 +230,12 @@ if [ $run_tests -eq 1 ]; then
"gdb --version"
"jq --version"
"echo 'puts [info patchlevel]' | tclsh"
"rustc --version"
"rust-gdb --version"
"evcxr --version"
"sqlite3 --version"
"tsc --version"
"ts-node --version"
)


Expand Down
15 changes: 14 additions & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ gotty: asset ${TARGET}/main.go utils/*.go server/*.go webtty/*.go filebrowser/*.
#godep go build ${BUILD_OPTIONS}

.PHONY: asset
asset: bindata/static/js/gotty-bundle.js bindata/static/js/jsconsole.js bindata/static/index.html bindata/static/doc.html bindata/static/editblog.html bindata/static/about.html bindata/static/NewFile.html bindata/static/images bindata/static/css bindata/static/css/xterm.css bindata/static/meta
asset: bindata/static/js/gotty-bundle.js bindata/static/js/chat-widget.js bindata/static/js/jsconsole.js bindata/static/index.html bindata/static/doc.html bindata/static/editblog.html bindata/static/about.html bindata/static/NewFile.html bindata/static/images bindata/static/css bindata/static/css/xterm.css bindata/static/meta
$(ROOT)/bin/go-bindata -prefix bindata -pkg server -ignore=\\.gitkeep -o server/asset.go bindata/...
GO111MODULE=off $(GOROOT)/bin/gofmt -w server/asset.go

Expand Down Expand Up @@ -108,6 +108,16 @@ jsconsole/build/static/js/jsconsole.js: jsconsole/node_modules/webpack $(JS_FILE
bindata/static/js/jsconsole.js: jsconsole/build/static/js/jsconsole.js
cp jsconsole/build/static/js/jsconsole.js bindata/static/js/jsconsole.js

CHAT_JS_FILES := $(wildcard resources/chat-widget/src/widget.*) $(wildcard resources/chat-widget/*.json) $(wildcard resources/chat-widget/*.js) resources/chat-widget/src/index.ts resources/chat-widget/src/openreplkeywords.ts

resources/chat-widget/dist/index.umd.js: $(CHAT_JS_FILES)
@echo "building chat-widget: "
cd resources/chat-widget && \
npm install

bindata/static/js/chat-widget.js: resources/chat-widget/dist/index.umd.js
cp resources/chat-widget/dist/index.umd.js bindata/static/js/chat-widget.js

deb: all
mkdir -p ${DEBIAN_ROOT}/gotty/usr/lib/systemd/system
mkdir -p ${DEBIAN_ROOT}/gotty/usr/local/bin
Expand Down Expand Up @@ -141,6 +151,9 @@ clean:
cleanjs:
rm -rf js/node_modules
rm -rf jsconsole/node_modules
rm -rf resources/chat-widget/node_modules
rm -rf js/dist/*
rm -rf resources/chat-widget/dist/*
@echo ".... Clean Done"


Expand Down
1 change: 1 addition & 0 deletions src/backend/localcommand/local_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ func New(command string, argv []string, ppid int, params url.Values, options ...
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, "TERM=xterm")
cmd.Env = append(cmd.Env, "GOPATH=/opt/gotty/")
cmd.Env = append(cmd.Env, "GOCACHE=/tmp/go_cache/.cache/go-build/")
cmd.Env = append(cmd.Env, "HOME="+cmd.Dir)
cmd.Env = append(cmd.Env, "HOSTNAME="+command)
cmd.Env = append(cmd.Env, "GCC_EXEC_PREFIX=/usr/lib/gcc/")
Expand Down
3 changes: 3 additions & 0 deletions src/containers/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ var Commands2memLimitMap = map[string]int64{
"jq-repl": 2,
"tclsh": 2,
"java": 128, // jvm takes lot of memory
"evcxr": 50, // rust REPL
"sqlite3": 10,
"ts-node": 50,
}

var memLimitMutex sync.Mutex
Expand Down
105 changes: 96 additions & 9 deletions src/cookie/cookie.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
)

const MAX_CONN_PER_BROWSER = 1
// this key will be used for encryption and decdryption of tokens
var SECRET_KEY []byte = encoder.GenerateLargePrime().Bytes()

// handling for cookies and incrementing session cookie counter
func IncrementCounterCookies(rw http.ResponseWriter, req *http.Request) {
Expand Down Expand Up @@ -68,8 +70,8 @@ func GetCounterCookieValue(req *http.Request) int {
var session_store *sessions.CookieStore

// initilize the cookiestore with secret stored in session DB
func Init_SessionStore(secret string) {
session_store = sessions.NewCookieStore([]byte(secret))
func Init_SessionStore(secret []byte) {
session_store = sessions.NewCookieStore(secret)
}

func Get_SessionStore() *sessions.CookieStore {
Expand All @@ -82,14 +84,15 @@ func init() {
panic(errors.New("uninitialized session_db_handle!!"))
}
secret , err := session_db_handle.Fetch([]byte(user.SESSION_KEY))
log.Println("secret: ", secret, err)
log.Println("secret fetched: ", err)
if err != nil {
// failed to fetch secret, generate a temporary secret for this instance
secret = encoder.GenerateLargePrime().Bytes()
log.Println("Failed to fetch secret for session_cookie, generated temporary secret: ", secret, err)
log.Println("Failed to fetch secret for session_cookie, generated temporary secret. ", err)
}
SECRET_KEY = secret
// init one time session store using SESSION_KEY
Init_SessionStore(string(secret))
Init_SessionStore(secret)

}

Expand All @@ -107,14 +110,23 @@ func Set_SessionCookie(rw http.ResponseWriter, req *http.Request, session user.U
session_cookie.Values ["expirationTime"] = session.ExpirationTime
session_cookie.Values [utils.HOME_DIR_KEY] = user.GetHomeDir(session.Uid)

// number of api request remaining in seconds
var req_count_rem float64 = float64(session.ExpirationTime-utils.GetUnixMilli())/1000
// set maxage of the session
session_cookie.Options = &sessions.Options{
Path: "/",
MaxAge: int(session.ExpirationTime-utils.GetUnixMilli())/1000,
MaxAge: int(req_count_rem),
}

log.Println("session cookie save: ", int(session.ExpirationTime-utils.GetUnixMilli())/1000, session_cookie)
if session.LoggedIn {
session_cookie.Values[utils.OPENAI_REQUEST_COUNT_KEY] = (req_count_rem/60)*utils.USER_FACTOR
} else {
session_cookie.Values[utils.OPENAI_REQUEST_COUNT_KEY] = (req_count_rem/60)*utils.GUEST_FACTOR
}

log.Println("session cookie save: ", int(session.ExpirationTime-utils.GetUnixMilli())/1000)
return session_store.Save(req, rw, session_cookie)

}


Expand All @@ -127,6 +139,8 @@ func Delete_SessionCookie(rw http.ResponseWriter, req *http.Request, session use
session_cookie.Values["uid"] = session.Uid
session_cookie.Values["sessionID"] = session.SessionID
session_cookie.Values ["loggedIn"] = false
delete(session_cookie.Values, utils.OPENAI_REQUEST_COUNT_KEY)
delete(session_cookie.Values, utils.OPENAI_REQUEST_LAST_ACCESS)

// set maxage of the session
session_cookie.Options = &sessions.Options{
Expand Down Expand Up @@ -187,6 +201,78 @@ func IsSessionExpired(req *http.Request) bool {
return false
}

func GetOpenApiRequestCount(req *http.Request) (count float64) {
session_cookie, _ := session_store.Get(req, "user-session")
val := session_cookie.Values[utils.OPENAI_REQUEST_COUNT_KEY]
count, ok := val.(float64);
if !ok {
return float64(0)
}
return count
}

func SetOpenApiRequestCount(rw http.ResponseWriter, req *http.Request, count float64) (err error) {
session_cookie, _ := session_store.Get(req, "user-session")
session_cookie.Values[utils.OPENAI_REQUEST_COUNT_KEY] = count
return session_store.Save(req, rw, session_cookie)
}

func GetOpenApiLastAccessTime(req *http.Request) (lastaccesstime int64) {
session_cookie, _ := session_store.Get(req, "user-session")
val := session_cookie.Values[utils.OPENAI_REQUEST_LAST_ACCESS]
lastaccesstime, ok := val.(int64);
if !ok {
return utils.GetUnixMilli() - utils.DEADLINE_MINUTES*60*1000
}
return lastaccesstime
}

/*
to be called whenever openAIapi request is made, to recharge the request count
based on current time lapsed, it should eb able to give n number of requests per minute,
as given by user or GUEST_FACTOR
*/
func UpdateOpenApiRequestCountBalance(rw http.ResponseWriter, req *http.Request) (err error) {
session_cookie, _ := session_store.Get(req, "user-session")
// recharge req_count balance in sec
current_time_mili := utils.GetUnixMilli()
var req_count_balance_sec float64 = float64(current_time_mili-GetOpenApiLastAccessTime(req))/1000

var req_count_balance float64 = 0
var max_cap float64 = utils.GUEST_FACTOR*utils.DEADLINE_MINUTES // max num of request per minute a user can make
if Is_UserLoggedIn(req) {
req_count_balance = GetOpenApiRequestCount(req)+(req_count_balance_sec/60)*utils.USER_FACTOR
max_cap = utils.USER_FACTOR*utils.DEADLINE_MINUTES
} else {
req_count_balance = GetOpenApiRequestCount(req)+(req_count_balance_sec/60)*utils.GUEST_FACTOR
max_cap = utils.GUEST_FACTOR*utils.DEADLINE_MINUTES
}
if max_cap >= req_count_balance {
session_cookie.Values[utils.OPENAI_REQUEST_COUNT_KEY] = req_count_balance
} else {
session_cookie.Values[utils.OPENAI_REQUEST_COUNT_KEY] = max_cap
}
// not exceeding request balance more that maxcap req per user
session_cookie.Values[utils.OPENAI_REQUEST_LAST_ACCESS] = current_time_mili
return session_store.Save(req, rw, session_cookie)
}

func GetOpenApiAccessToken(req *http.Request) (acc_token, secret []byte) {
session_cookie, _ := session_store.Get(req, "user-session")
val := session_cookie.Values[utils.ACCESS_TOKEN_KEY]
secretval := session_cookie.Values[utils.ACCESS_SECRET_KEY]
acc_token, _ = val.([]byte);
secret, _ = secretval.([]byte);
return acc_token, secret
}

func SetOpenApiAccessToken(rw http.ResponseWriter, req *http.Request, acc_token, secret []byte) (err error) {
session_cookie, _ := session_store.Get(req, "user-session")
session_cookie.Values[utils.ACCESS_TOKEN_KEY] = acc_token
session_cookie.Values[utils.ACCESS_SECRET_KEY] = secret
return session_store.Save(req, rw, session_cookie)
}

func Get_SessionCookie(req *http.Request) (session user.UserSession) {
session.Uid = Get_Uid(req)
session.SessionID = Get_SessionID(req)
Expand All @@ -205,6 +291,7 @@ func UpdateGuestSessionCookieAge(rw http.ResponseWriter, req *http.Request, newa

if !Is_UserLoggedIn(req) || IsSessionExpired(req) {
// only update age if user not logged in

maxage = newage
}
// update maxage (sec) of the session
Expand All @@ -213,7 +300,7 @@ func UpdateGuestSessionCookieAge(rw http.ResponseWriter, req *http.Request, newa
MaxAge: maxage,
}
err = session_store.Save(req, rw, session_cookie)
log.Println("session cookie save: ", maxage, session_cookie, "Error: ", err)
log.Println("session cookie save: ", maxage, "Error: ", err)
return err
}

Expand Down Expand Up @@ -244,7 +331,7 @@ func GetOrUpdateHomeDir(rw http.ResponseWriter, req *http.Request, Uid string) (
var ok bool

homedir, ok = session_cookie.Values[utils.HOME_DIR_KEY].(string);
log.Println("previous homedir: ", homedir, ok, session_cookie)
log.Println("previous homedir: ", homedir, ok)
// check if same uid amd valid home dir, if not generate a new homedir
if Uid!=Get_Uid(req) || !ok || homedir=="" {
homedir = user.GetHomeDir(Uid)
Expand Down
Loading
Loading