267 lines
9.3 KiB
Lua
267 lines
9.3 KiB
Lua
require("net")
|
|
--General Stuff
|
|
--[[ What this module does!
|
|
Adds
|
|
net.identity:init()
|
|
|
|
]]
|
|
net:registerModule("identity",{2,1,0})--1.0.1 Note: Added eaiser ways to get user data using only cid
|
|
function net.hash(text,n)
|
|
n=n or 16
|
|
return bin.new(text.."jgmhktyf"):getHash(n)
|
|
end
|
|
net.identity.UIDS={}
|
|
net.identity.UIDS.ids={}
|
|
function net.identity:init() -- calling this initilizes the library and binds it to the servers and clients created
|
|
--Server Stuff
|
|
net.OnServerCreated(function(s)
|
|
s.userFolder="./USERS"
|
|
print("The identity Module has been loaded onto the server!")
|
|
function s:_isRegistered(user)
|
|
return io.fileExists(self.userFolder..net.hash(user)..".dat")
|
|
end
|
|
function s:getUserData(user)
|
|
local userdata=bin.load(self.userFolder..net.hash(user)..".dat")
|
|
local nick,dTable=userdata:match("%S-|%S-|(%S-)|(.+)")
|
|
return nick,loadstring("return "..(dTable or "{}"))()
|
|
end
|
|
function s:modifyUserData(user,oldpass,pass,nick,dTable)
|
|
if self:_isRegistered(user) then
|
|
local userdata=bin.load(self.userFolder..net.hash(user)..".dat")
|
|
local args={}
|
|
local _pass,_nick,_dTable=userdata:match("%S-|(%S-)|(%S-)|(.+)")
|
|
if oldpass~=_pass then
|
|
args.invalidPass=true
|
|
pass=_pass
|
|
end
|
|
if not nick then nick=_nick args.invalidNick=true end
|
|
table.merge(_dTable or {}, dTable or {})
|
|
bin.new(string.format("%s|%s|%s|%s\n",user,pass,nick,dTable)):tofile(self.userFolder..net.hash(user)..".dat")
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
function s:getUserCred(user)
|
|
local userdata=bin.load(self.userFolder..net.hash(user)..".dat")
|
|
return userdata:match("%S-|(%S-)|")
|
|
end
|
|
function s:getUSERID(cid)
|
|
return (net.identity.UIDS[cid] or "User Not Logged In!")
|
|
end
|
|
function s:getUsername(cid)
|
|
return self:userLoggedIn(cid)
|
|
end
|
|
function s:getNickname(cid)
|
|
return self.loggedIn[self:getUsername(cid)].nick
|
|
end
|
|
function s:getdTable(cid)
|
|
return self.loggedIn[self:getUsername(cid)]
|
|
end
|
|
function s:getUserDat(cid)
|
|
return self:getUserDataHandle(self:getUsername(cid))
|
|
end
|
|
function s:getNickFromUSERID(USERID)
|
|
return bin.load(self.userFolder..net.hash(user)..".dat"):match("%S-|%S-|(%S-)|")
|
|
end
|
|
function s:userLoggedIn(cid)
|
|
for i,v in pairs(self.loggedIn) do
|
|
if v.cid==cid then
|
|
return i
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
function s:setDataLocation(loc)
|
|
if not io.dirExists(loc) then
|
|
io.mkDir(loc)
|
|
end
|
|
self.userFolder=loc
|
|
end
|
|
s:setDataLocation("USERS/")
|
|
function s:logoutUser(user)
|
|
net.identity.UIDS.ids[user.UID]=nil
|
|
self.loggedIn[user]=nil
|
|
end
|
|
function s:loginUser(user,cid)
|
|
net.identity.UIDS[cid]=net.hash(user)
|
|
local nick,dTable=self:getUserData(user)
|
|
self.loggedIn[user]={}
|
|
table.merge(self.loggedIn[user],dTable or {})
|
|
self.loggedIn[user].cid=cid
|
|
self.loggedIn[user].nick=nick
|
|
self.loggedIn[user].UID=net.resolveID(net.identity.UIDS)
|
|
return self.loggedIn[user]
|
|
end
|
|
function s:getUserDataHandle(user)
|
|
return self.loggedIn[user]
|
|
end
|
|
function s:syncUserData(user,ip,port)
|
|
local handle=self:getUserDataHandle(user)
|
|
self:send(ip,"!identity! SYNC <-|"..bin.ToStr(handle).."|->",port)
|
|
end
|
|
s.loggedIn={}
|
|
s.allowDuplicateNicks=true
|
|
s.minimumNickLength=4
|
|
s.minimumUserLength=4
|
|
s.OnUserRegistered=multi:newConnection()
|
|
s.OnUserLoggedIn=multi:newConnection()
|
|
s.OnUserLoggerOut=multi:newConnection()
|
|
s.OnAlreadyLoggedIn=multi:newConnection()
|
|
s.OnPasswordForgotten=multi:newConnection()
|
|
s.OnDataRecieved:connect(function(self,data,cid,ip,port) -- when the server recieves data this method is triggered
|
|
local cmd,arg1,arg2,arg3,arg4 = data:match("!identity! (%S-) '(.-)' '(.-)' '(.-)' <%-|(.+)|%->")
|
|
if cmd=="register" then
|
|
local user,pass,nick,dTable = arg1,arg2,arg3,arg4
|
|
if self:_isRegistered(user) then
|
|
self:send(ip,"!identity! REGISTERED <-|"..user.."|->",port)
|
|
else
|
|
if not(self.userFolder:sub(-1,-1)=="/" or self.userFolder:sub(-1,-1)=="\\") then
|
|
self.userFolder=self.userFolder.."/"
|
|
end
|
|
local rets=self.OnUserRegistered:Fire(user,pass,nick,loadstring("return "..(dTable or "{}"))())
|
|
if #user<=self.minimumUserLength then
|
|
self:send(ip,"!identity! REGISTERREFUSED <-|Username too short|->",port)
|
|
return
|
|
end
|
|
if #user<=self.minimumNickLength then
|
|
self:send(ip,"!identity! REGISTERREFUSED <-|Nickname too short|->",port)
|
|
return
|
|
end
|
|
for i=1,#rets do
|
|
if rets[i][1]==false then
|
|
print("Server refused to accept registration request!")
|
|
self:send(ip,"!identity! REGISTERREFUSED <-|Unspecified Error|->",port)
|
|
return
|
|
end
|
|
end
|
|
multi:newFunction(function(func) -- anom func, allows for fancy multitasking
|
|
local dupnickfilemanager=bin.stream(self.userFolder.."Nicks.dat",false)
|
|
local isValid=func:newCondition(function() return t~=nil end)
|
|
local tab={}
|
|
local t=dupnickfilemanager:getBlock("s")
|
|
if self.allowDuplicateNicks==false then
|
|
while func:condition(isValid) do
|
|
tab[#tab]=t
|
|
if t==nick then
|
|
self:send(ip,"!identity! REGISTERREFUSED <-|Duplicate Nicks are not allowed|->",port)
|
|
dupnickfilemanager:close()
|
|
return
|
|
end
|
|
end
|
|
t=dupnickfilemanager:getBlock("s")
|
|
end
|
|
dupnickfilemanager:addBlock(nick.."|"..bin.new(user):getHash(32))
|
|
dupnickfilemanager:close()
|
|
bin.new(string.format("%s|%s|%s|%s\n",user,pass,nick,dTable)):tofile(self.userFolder..net.hash(user)..".dat")
|
|
self:send(ip,"!identity! REGISTEREDGOOD <-|"..user.."|->",port)
|
|
func=nil -- we dont want 1000s+ of these anom functions lying around
|
|
return
|
|
end)()-- lets call the function
|
|
end
|
|
return
|
|
elseif cmd=="login" then
|
|
local user,pass = arg1,arg2
|
|
local _pass=s:getUserCred(user)
|
|
if not(self:_isRegistered(user)) then
|
|
self:send(ip,"!identity! LOGINBAD <-|nil|->",port)
|
|
return
|
|
end
|
|
if pass==_pass then
|
|
if self:userLoggedIn(cid) then
|
|
self.OnAlreadyLoggedIn:Fire(self,user,cid,ip,port)
|
|
self:send(ip,"!identity! ALREADYLOGGEDIN <-|nil|->",port)
|
|
return
|
|
end
|
|
local handle=self:loginUser(user,cid) -- binds the cid to username
|
|
self:send(ip,"!identity! LOGINGOOD <-|"..bin.ToStr(handle).."|->",port)
|
|
self.OnUserLoggedIn:Fire(user,cid,ip,port,bin.ToStr(handle))
|
|
return
|
|
else
|
|
self:send(ip,"!identity! LOGINBAD <-|nil|->",port)
|
|
return
|
|
end
|
|
elseif cmd=="logout" then
|
|
self:logoutUser(user)
|
|
self.OnClientClosed:Fire(self,"User logged out!",cid,ip,port)
|
|
elseif cmd=="sync" then
|
|
local dTable = loadstring("return "..(arg4 or "{}"))()
|
|
local handle = self:getUserDataHandle(self:userLoggedIn(cid))
|
|
table.merge(handle,dTable)
|
|
elseif cmd=="pass" then
|
|
local user=arg1
|
|
if self:_isRegistered(user) then
|
|
self.OnPasswordForgotten:Fire(arg1,cid)
|
|
self:send(ip,"!identity! PASSREQUESTHANDLED <-|NONE|->",port)
|
|
else
|
|
self:send(ip,"!identity! NOUSER <-|"..user.."|->",port)
|
|
end
|
|
end
|
|
end)
|
|
s.OnClientClosed:connect(function(self,reason,cid,ip,port)
|
|
self.OnUserLoggerOut:Fire(self,self:userLoggedIn(cid),cid,reason)
|
|
end)
|
|
end,"identity")
|
|
--Client Stuff
|
|
net.OnClientCreated:connect(function(c)
|
|
c.userdata={}
|
|
c.OnUserLoggedIn=multi:newConnection()
|
|
c.OnBadLogin=multi:newConnection()
|
|
c.OnUserAlreadyRegistered=multi:newConnection()
|
|
c.OnUserAlreadyLoggedIn=multi:newConnection()
|
|
c.OnUserRegistered=multi:newConnection()
|
|
c.OnNoUserWithName=multi:newConnection()
|
|
c.OnPasswordRequest=multi:newConnection()
|
|
c.OnUserRegisterRefused=multi:newConnection()
|
|
function c:logout()
|
|
self:send("!identity! logout 'NONE' 'NONE' 'NONE' <-|nil|->")
|
|
end
|
|
c.OnDataRecieved(function(self,data) -- when the client recieves data this method is triggered
|
|
local cmd,arg1 = data:match("!identity! (%S-) <%-|(.+)|%->")
|
|
if cmd=="REGISTERED" then
|
|
self.OnUserAlreadyRegistered:Fire(self,arg1)
|
|
elseif cmd=="REGISTEREDGOOD" then
|
|
self.OnUserRegistered:Fire(self,arg1)
|
|
elseif cmd=="REGISTERREFUSED" then
|
|
self.OnUserRegisterRefused:Fire(self,arg1)
|
|
elseif cmd=="ALREADYLOGGEDIN" then
|
|
self.OnUserAlreadyLoggedIn:Fire(self,arg1)
|
|
elseif cmd=="LOGINBAD" then
|
|
self.OnBadLogin:Fire(self)
|
|
elseif cmd=="LOGINGOOD" then
|
|
local dTable=loadstring("return "..(arg1 or "{}"))()
|
|
table.merge(self.userdata,dTable)
|
|
self.OnUserLoggedIn:Fire(self,self.userdata)
|
|
elseif cmd=="SYNC" then
|
|
local dTable=loadstring("return "..(arg1 or "{}"))()
|
|
table.merge(self.userdata,dTable)
|
|
elseif cmd=="NOUSER" then
|
|
self.OnNoUserWithName:Fire(self,arg1)
|
|
elseif cmd=="PASSREQUESTHANDLED" then
|
|
self.OnPasswordRequest:Fire(self)
|
|
end
|
|
end,"identity")
|
|
function c:syncUserData()
|
|
self:send(string.format("!identity! sync 'NONE' 'NONE' 'NONE' <-|%s|->",bin.ToStr(dTable)))
|
|
end
|
|
function c:forgotPass(user)
|
|
self:send(string.format("!identity! pass '%s' 'NONE' 'NONE' <-|nil|->",user))
|
|
end
|
|
function c:getUserDataHandle()
|
|
return self.userdata
|
|
end
|
|
function c:logIn(user,pass)
|
|
self:send(string.format("!identity! login '%s' '%s' 'NONE' <-|nil|->",user,net.hash(pass)))
|
|
end
|
|
function c:register(user,pass,nick,dTable)
|
|
if dTable then
|
|
self:send(string.format("!identity! register '%s' '%s' '%s' <-|%s|->",user,net.hash(pass),nick,bin.ToStr(dTable)))
|
|
else
|
|
self:send(string.format("!identity! register '%s' '%s' '%s' <-|nil|->",user,net.hash(pass),nick))
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
if net.autoInit then
|
|
net.identity:init()
|
|
end
|