mirror of
https://github.com/Open-Argon/isotope-server.git
synced 2026-10-28 09:43:51 +00:00
190 lines
6.2 KiB
Plaintext
190 lines
6.2 KiB
Plaintext
let packages = {}
|
|
let accounts = []
|
|
let indexes = {username: {}, email: {}, id: {}}
|
|
let savePath = path.join([program.cwd, 'data', "packages-db.json"])
|
|
|
|
let changes = {n: 0, last: 0}
|
|
|
|
let validVersion(version) = do
|
|
if (version.length < 1 || version.length > 16) return false
|
|
for (i from 0 to version.length) do
|
|
if (i > 0 && i < version.length-1) do
|
|
if (version[i] not in "abcdefghijklmnopqrstuvwxyz0123456789-.") return false
|
|
else if (version[i] not in "abcdefghijklmnopqrstuvwxyz0123456789") return false
|
|
return true
|
|
|
|
let validName(name) = do
|
|
if (name.length < 3 || name.length > 32) return false
|
|
for (i from 0 to name.length) do
|
|
if (i > 0 && i < name.length-1) do
|
|
if (name[i] not in "abcdefghijklmnopqrstuvwxyz0123456789-.") return false
|
|
else if (name[i] not in "abcdefghijklmnopqrstuvwxyz0123456789") return false
|
|
return true
|
|
|
|
let makeChange() = changes.n += 1
|
|
|
|
let randstr(length) = do
|
|
let chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
|
let str = []
|
|
for (i from 0 to length) do
|
|
str.append(chars[random.int(0, chars.length-1)])
|
|
return str.join("")
|
|
|
|
let load() = do
|
|
if (path.exists(savePath)) do
|
|
let file = file.read(savePath)
|
|
data = file.json()||{}
|
|
if ("packages" not in data) do
|
|
packages = data
|
|
accounts = []
|
|
makeChange()
|
|
else do
|
|
packages = data.packages
|
|
accounts = data.accounts
|
|
file.close()
|
|
|
|
let forceSave() = do
|
|
makeChange()
|
|
save()
|
|
|
|
let save() = do
|
|
if (changes.n == changes.last) return
|
|
changes.last = changes.n
|
|
let file = file.write(savePath)
|
|
file.json({packages: packages, accounts: accounts})
|
|
file.close()
|
|
|
|
let saveThread() = do
|
|
forever do
|
|
try do
|
|
save()
|
|
catch (e) do
|
|
term.log(e)
|
|
time.snooze(10)
|
|
|
|
let account = {}
|
|
|
|
account.addToIndexes(acc, index) = do
|
|
indexes.username[acc.username] = index
|
|
indexes.email[acc.email] = index
|
|
indexes.id[acc.id] = index
|
|
|
|
account.makeId() = do
|
|
let id = "u-"+randstr(32)
|
|
if (account.getById(id) != null) return account.makeId()
|
|
return id
|
|
|
|
account.getById(id) = do
|
|
if (id in indexes.id) return accounts[indexes.id[id]]
|
|
for (i from 0 to accounts.length) do
|
|
if (accounts[i].id == id) do
|
|
account.addToIndexes(accounts[i], i)
|
|
return accounts[i]
|
|
return null
|
|
|
|
account.getByUsername(username) = do
|
|
if (username in indexes.username) return accounts[indexes.username[username]]
|
|
for (i from 0 to accounts.length) do
|
|
if (accounts[i].username == username) do
|
|
account.addToIndexes(accounts[i], i)
|
|
return accounts[i]
|
|
return null
|
|
|
|
account.getByEmail(email) = do
|
|
if (email in indexes.email) return accounts[indexes.email[email]]
|
|
for (i from 0 to accounts.length) do
|
|
if (accounts[i].email == email) do
|
|
account.addToIndexes(accounts[i], i)
|
|
return accounts[i]
|
|
return null
|
|
|
|
account.getByToken(token) = do
|
|
let split = token.splitN("|", 2)
|
|
if (split.length != 2) return null
|
|
let id = split[0]
|
|
let token = split[1]
|
|
let acc = account.getById(id)
|
|
if (acc == null) return null
|
|
if (token not in acc.tokens) return null
|
|
return acc
|
|
|
|
account.deleteToken(token) = do
|
|
let split = token.split("|")
|
|
if (split.length != 2) return false
|
|
let id = split[0]
|
|
let token = split[1]
|
|
let acc = account.getById(id)
|
|
if (acc == null) return false
|
|
if (token not in acc.tokens) return false
|
|
acc.tokens = acc.tokens.filter((t) = t != token)
|
|
forceSave()
|
|
return true
|
|
|
|
account.makeToken(acc) = do
|
|
let token = randstr(100)
|
|
acc.tokens.append(token)
|
|
makeChange()
|
|
return acc.id+"|"+token
|
|
|
|
account.saltHash(password, salt) = sha256(password+salt)
|
|
|
|
account.validPassword(password) = do
|
|
if (password.length < 8) return "Password must be at least 8 characters"
|
|
# include at least one number
|
|
let hasNumber = false
|
|
for (i from 0 to password.length) do
|
|
if (password[i] in "0123456789") do
|
|
hasNumber = true
|
|
break
|
|
if (not hasNumber) return "Password must include at least one number"
|
|
# include at least one uppercase letter
|
|
if (password.lower() == password) return "Password must include at least one uppercase letter"
|
|
# include at least one lowercase letter
|
|
if (password.upper() == password) return "Password must include at least one lowercase letter"
|
|
return null
|
|
|
|
account.validEmail(email) = do
|
|
let split = email.split("@")
|
|
if (split.length != 2) return false
|
|
if (split[0].length == 0) return false
|
|
if (" " in split[0]) return false
|
|
if (split[1].length == 0) return false
|
|
if (" " in split[1]) return false
|
|
if (split[1].split(".").length < 2) return false
|
|
return true
|
|
|
|
account.validUsername(username) = do
|
|
if (username.length < 3) return false
|
|
if (username.length > 32) return false
|
|
for (i from 0 to username.length) do
|
|
if (username[i] not in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_") return false
|
|
return true
|
|
|
|
|
|
account.create(username, email, password) = do
|
|
if (not account.validUsername(username)) return {error: "Invalid username"}
|
|
if (not account.validEmail(email)) return {error: "Invalid email"}
|
|
if (account.getByUsername(username) != null) return {error: "Username already exists"}
|
|
if (account.getByEmail(email) != null) return {error: "Email already exists"}
|
|
if ((let error = account.validPassword(password)) != null) return {error: error}
|
|
let id = account.makeId()
|
|
let salt = randstr(100)
|
|
let hash = account.saltHash(password, salt)
|
|
let acc = {id: id, username: username, email:email, password: hash, salt: salt, tokens: []}
|
|
accounts.append(acc)
|
|
forceSave()
|
|
return acc
|
|
|
|
account.login(user, password) = do
|
|
let acc = account.getByUsername(user)
|
|
if (acc == null) do
|
|
acc = account.getByEmail(user)
|
|
if (acc == null) return {error: "Icorrect username or email"}
|
|
let hash = account.saltHash(password, acc.salt)
|
|
if (hash != acc.password) return {error: "Incorrect password"}
|
|
return {token: account.makeToken(acc)}
|
|
|
|
|
|
load()
|
|
t = thread(saveThread)
|
|
t.start() |