Commit 1478ca36 authored by Ricardo Cosme's avatar Ricardo Cosme

Merge branch 'OPENBUS-2970' into '02_00_00'

[OPENBUS-2970] Migração da base de dados do barramento para SQLite3

+ Ajustes necessários para o uso da nova versão do módulo database.lua que suporta a biblioteca SQLite3.

See merge request !1
parents 6e5a0f9d caca16a0
......@@ -98,6 +98,13 @@ if ! $(luaopenbus)
}
use-project luaopenbus : $(luaopenbus)/bbuild ;
local luasqlite3 = [ os.environ LUASQLITE3 ] ;
if ! $(luasqlite3)
{
luasqlite3 = "$(deps)/luasqlite3" ;
}
use-project luasqlite3 : $(luasqlite3)/bbuild ;
local openldap-jam = [ os.environ OPENLDAP_JAM ] ;
if ! $(openldap-jam)
{
......@@ -208,6 +215,8 @@ local exe_deps =
/oil//luaidl
/luascs//luascs
/luaopenbus//luaopenbus
/sqlite//sqlite3
/luasqlite3//lsqlite3
;
local exe_requirements =
......
......@@ -88,6 +88,8 @@ local assertCaller = coreutil.assertCaller
local MaxEncryptedData = strrep("\255", EncryptedBlockSize-11)
local lsqlite = require "lsqlite3"
------------------------------------------------------------------------------
-- Faceta CertificateRegistry
------------------------------------------------------------------------------
......@@ -110,8 +112,11 @@ local CertificateRegistry = { __type = CertificateRegistryType }
function CertificateRegistry:__init(data)
self.database = data.database
self.certificateDB = assert(self.database:gettable("Certificates"))
local certificates = {}
for entry in self.database.pstmts.getCertificate:nrows() do
certificates[entry.entity] = entry.certificate
end
self.certificates = certificates
local access = data.access
local admins = data.admins
access:setGrantedUsers(self.__type, "registerCertificate", admins)
......@@ -121,7 +126,7 @@ function CertificateRegistry:__init(data)
end
function CertificateRegistry:getPublicKey(entity)
local certificate, errmsg = self.certificateDB:getentry(entity)
local certificate = self:getCertificate(entity)
if certificate ~= nil then
return assert(assert(decodecertificate(certificate)):getpubkey())
elseif errmsg ~= nil then
......@@ -148,15 +153,17 @@ function CertificateRegistry:registerCertificate(entity, certificate)
InvalidCertificate{entity=entity,message=errmsg}
end
log:admin(msg.RegisterEntityCertificate:tag{entity=entity})
assert(self.certificateDB:setentry(entity, certificate))
if not self.certificates[entity] then
assert(self.database:pexec("addCertificate", certificate, entity))
else
assert(self.database:pexec("setCertificate", certificate, entity))
end
self.certificates[entity] = certificate
end
function CertificateRegistry:getCertificate(entity)
local certificate, errmsg = self.certificateDB:getentry(entity)
if certificate == nil then
if errmsg ~= nil then
assert(nil, errmsg)
end
local certificate = self.certificates[entity]
if not certificate then
MissingCertificate{entity=entity}
end
return certificate
......@@ -164,17 +171,20 @@ end
function CertificateRegistry:getEntitiesWithCertificate()
local entities = {}
for entity in self.certificateDB:ientries() do
entities[#entities+1] = entity
for entity in pairs(self.certificates) do
entities[#entities+1] = entity
end
return entities
end
function CertificateRegistry:removeCertificate(entity)
local db = self.certificateDB
if db:getentry(entity) ~= nil then
if self.certificates[entity] then
log:admin(msg.RemoveEntityCertificate:tag{entity=entity})
assert(db:removeentry(entity))
local delCertificate = self.database.pstmts.delCertificate
delCertificate:bind_values(entity)
delCertificate:step()
delCertificate:reset()
self.certificates[entity] = nil
return true
end
return false
......@@ -243,12 +253,19 @@ local AccessControl = {
-- local operations
function AccessControl:__init(data)
local database = data.database
local autosets = assert(database:gettable("AutoSetttings"))
local busid = autosets:getentry("BusId")
local db = data.database
-- TODO
local getSettings = db.pstmts.getSettings
getSettings:bind_values("BusId")
local ret = getSettings:step()
local busid
if ret == lsqlite.ROW then
busid = getSettings:get_value(0)
getSettings:reset()
end
if busid == nil then
busid = newid("time")
assert(autosets:setentry("BusId", busid))
assert(db:pexec("addSettings", "BusId", busid))
log:action(msg.AdoptingNewBusIdentifier:tag{bus=busid})
else
log:action(msg.RecoveredBusIdentifier:tag{bus=busid})
......@@ -270,7 +287,7 @@ function AccessControl:__init(data)
limit = data.passwordFailureLimit,
period = data.passwordFailureLimit/data.passwordFailureRate,
}
self.activeLogins = Logins{ database = database }
self.activeLogins = Logins{ database = db }
-- initialize access
self.busid = busid
......
......@@ -37,7 +37,13 @@ local function setWatchedOf(self, login, new)
watched[loginId] = new
-- try to update saved data
local id = self.id
local success, errmsg = self.table:setentryfield(id, "watched", watched)
local db = self.base.database
local success, errmsg
if new == true then
success, errmsg = assert(db:pexec("addWatchedLogin", id, loginId))
else
success, errmsg = assert(db:pexec("delWatchedLogin", id, loginId))
end
if success then
-- commit the changes in memory
login.watchers[self] = new
......@@ -57,10 +63,17 @@ function Observer:__init()
local base = self.base
local logins = base.logins
logins[self.login].observers[self] = true
for id in pairs(self.watched) do
local stmt = base.database.pstmts.getWatchedLoginByObserver
local observer_id = self.id
stmt:bind_values(observer_id)
local watched = {}
for entry in stmt:nrows() do
local id = entry.login
watched[id] = true
logins[id].watchers[self] = true
end
base.observers[self.id] = self
self.watched = watched
base.observers[observer_id] = self
end
function Observer:watchLogin(login)
......@@ -81,8 +94,9 @@ end
function Observer:remove()
local id = self.id
assert(self.table:removeentry(id))
local base = self.base
local db = base.database
assert(db:pexec("delLoginObserver", id))
local logins = base.logins
logins[self.login].observers[self] = nil
for id in pairs(self.watched) do
......@@ -104,19 +118,20 @@ end
function Login:newObserver(callback, legacy)
local base = self.base
local table = base.obsTab
local id = newid("time")
local ior = tostring(callback)
local login = self.id
local data = {
id = id,
login = self.id,
watched = {},
ior = tostring(callback),
login = login,
ior = ior,
legacy = legacy,
}
assert(table:setentry(id, data))
local db = base.database
legacy = (legacy and 1) or 0
assert(db:pexec("addLoginObserver", id, ior, legacy, login))
data.callback = callback
data.base = base
data.table = table
return Observer(data)
end
......@@ -141,7 +156,8 @@ function Login:remove()
end
-- remove this login
local id = self.id
assert(self.table:removeentry(id))
local db = self.base.database
assert(db:pexec("delLogin", id))
self.base.logins[id] = nil
-- notify all watchers
self.base.publisher:loginRemoved(self, watchers)
......@@ -155,28 +171,28 @@ function Database:__init()
self.observers = {}
self.publisher = Publisher(self.publisher)
local db = self.database
self.lgnTab = select(2, assert(pcall(readTable,
assert(db:gettable("Logins")),
Login,
self)))
self.obsTab = select(2, assert(pcall(readTable,
assert(db:gettable("LoginObservers")),
Observer,
self)))
for entry in db.pstmts.getLogin:nrows() do
entry.base = self
Login(entry)
end
for entry in db.pstmts.getLoginObserver:nrows() do
entry.base = self
Observer(entry)
end
end
function Database:newLogin(entity, encodedkey, allowLegacyDelegate)
local id = newid("time")
allowLegacyDelegate = (allowLegacyDelegate and 1) or 0
local data = {
id = id,
entity = entity,
encodedkey = encodedkey,
allowLegacyDelegate = allowLegacyDelegate or false,
allowLegacyDelegate = allowLegacyDelegate
}
local table = self.lgnTab
assert(table:setentry(id, data))
assert(self.database:pexec("addLogin", id, entity, encodedkey,
allowLegacyDelegate))
data.base = self
data.table = table
return Login(data)
end
......@@ -197,69 +213,3 @@ function Database:iObservers()
end
return Database
--[===[ This is a draft for a future implementation using SQLite3
local SQL_Schema = [[
CREATE TABLE IF NOT EXISTS Logins(
id TEXT(36) PRIMARY KEY,
entity TEXT NOT NULL)
CREATE TABLE IF NOT EXISTS Observers(
id TEXT(36) PRIMARY KEY,
entity TEXT NOT NULL,
ior TEXT NOT NULL,
FOREIGN KEY(entity) REFERENCES Logins(id))
CREATE TABLE IF NOT EXISTS ObservedLogins(
login TEXT(36) NOT NULL,
observer TEXT(36) NOT NULL,
PRIMARY KEY(login, observer),
FOREIGN KEY(login) REFERENCES Logins(id),
FOREIGN KEY(observer) REFERENCES Observers(id))
]]
local SQL_AddLogin = [[
INSERT INTO Logins VALUES (:id, :entity)
]]
local SQL_AddObserver = [[
INSERT INTO Observers VALUES (:id, :entity, :ior)
]]
local SQL_AddLoginToObserver = [[
INSERT INTO ObservedLogins VALUES (:login, :observer)
]]
local SQL_GetLogin = [[
SELECT entity
FROM Logins
WHERE id = $id
]]
local SQL_GetObserverIor = [[
SELECT ior
FROM Observers
WHERE id = $id
]]
local SQL_GetLoginObservers = [[
SELECT id, ior
FROM Observers JOIN ObservedLogins
WHERE observer = id AND login = $id
]]
local SQL_RemoveLogin = [[
DELETE FROM ObservedLogins WHERE login = $id
DELETE FROM ObservedLogins WHERE entity = (SELECT id FROM Observers WHERE entity = $id)
DELETE FROM Observers WHERE entity = $id
DELETE FROM Logins WHERE id = $id
]]
local SQL_RemoveObserver = [[
DELETE FROM ObservedLogins WHERE observer = $id
DELETE FROM Observers WHERE id = $id
]]
--]===]
\ No newline at end of file
This diff is collapsed.
-- $Id$
local removefile = os.remove
local renamefile = os.rename
local _G = require "_G"
local ipairs = _G.ipairs
......@@ -31,8 +33,12 @@ local running = cothread.running
local oillog = require "oil.verbose"
local log = require "openbus.util.logger"
local dbconverter = require "openbus.util.database_converter"
local dbconvert = dbconverter.convert
local database = require "openbus.util.database"
local opendb = database.open
local database_legacy = require "openbus.util.database_legacy"
local opendb_legacy = database_legacy.open
local server = require "openbus.util.server"
local ConfigArgs = server.ConfigArgs
local newSCS = server.newSCS
......@@ -70,6 +76,7 @@ return function(...)
InvalidChallengeTime = 14,
InvalidSharedAuthTime = 15,
InvalidMaximumChannelLimit = 16,
UnableToConvertLegacyDatabase = 17,
}
-- configuration parameters parser
......@@ -268,12 +275,51 @@ Options:
})
return errcode.UnableToReadPrivateKey
end
-- open database
local database, errmsg = opendb(Configs.database)
local dbpath = Configs.database
local dblegacy = opendb_legacy(dbpath)
local converted
if dblegacy then
local dbtmppath = dbpath..".convert"
local res, errmsg = opendb(dbtmppath)
if not res then
dbpath = dbtmppath
else
local dbtmp = res
res, errmsg = pcall(dbconvert, dblegacy, dbtmp)
if res then
local dbbakpath = dbpath..".bak"
res, errmsg = renamefile(dbpath, dbbakpath)
if not res then
errmsg = "unable to rename legacy database to '"..dbbakpath
.."' ("..errmsg..")"
else
res, errmsg = renamefile(dbtmppath, dbpath)
if not res then
errmsg = "unable to promote the converted database to '"..dbpath
.."' ("..errmsg..")"
else
converted = true
log:config(msg.ConvertedLegacyBusDatabase:tag{path=dbbakpath})
end
end
end
end
if not converted then
removefile(dbtmppath)
log:misconfig(msg.UnableToConvertLegacyDatabase:tag{
path = dbpath,
error = errmsg,
})
return errcode.UnableToConvertLegacyDatabase
end
end
local database, errmsg = opendb(dbpath)
if database == nil then
log:misconfig(msg.UnableToOpenDatabase:tag{
path = Configs.database,
path = dbpath,
error = errmsg,
})
return errcode.UnableToOpenDatabase
......
......@@ -20,6 +20,7 @@
#include "luascs.h"
#include "luaopenbus.h"
#include "coreservices.h"
#include "lsqlite3.h"
LUAMOD_API int luaopen_openbus_util_thread (lua_State *L);
......@@ -42,6 +43,7 @@ void luapreload_extralibraries(lua_State *L)
lua_pushcfunction(L,luaopen_struct);lua_setfield(L,-2,"struct");
lua_pushcfunction(L,luaopen_socket_core);lua_setfield(L,-2,"socket.core");
lua_pushcfunction(L,luaopen_openbus_util_thread);lua_setfield(L,-2,"openbus.util.thread");
lua_pushcfunction(L,luaopen_lsqlite3);lua_setfield(L,-2,"lsqlite3");
lua_pop(L, 1); /* pop 'package.preload' table */
/* preload other C libraries */
luapreload_lce(L);
......
......@@ -74,9 +74,9 @@ do
-- check login
local entity = login.entity
if entity == "delegator" then
assert(login.allowLegacyDelegate == true, "wrong stored login")
assert(login.allowLegacyDelegate == 1, "wrong stored login")
else
assert(login.allowLegacyDelegate == false, "wrong stored login")
assert(login.allowLegacyDelegate == 0, "wrong stored login")
end
-- check observers owned by this login
local observers = assert(Data[login.entity], "unknown stored login")
......@@ -171,75 +171,5 @@ end
do
local lfs = require "lfs"
assert(lfs.rmdir("test.db/Logins"))
assert(io.open("test.db/Logins", "w")):close()
assertEx("'test%.db/Logins' expected to be directory %(got file%)",
LoginDB, {database=assert(database.open("test.db"))})
assert(os.remove("test.db/Logins"))
assert(lfs.mkdir("test.db/Logins"))
local file = assert(io.open("test.db/Logins/corrupted.lua", "w"))
assert(file:write("illegal Lua code"))
file:close()
assertEx("unable to load file 'test%.db/Logins/corrupted%.lua'",
LoginDB, {database=assert(database.open("test.db"))})
assert(os.execute("chmod 000 test.db/Logins"))
assertEx("cannot open test%.db/Logins/: Permission denied",
LoginDB, {database=assert(database.open("test.db"))})
assert(os.execute("chmod 755 test.db/Logins"))
assert(os.remove("test.db/Logins/corrupted.lua"))
end
do
local logins = LoginDB{
database = assert(database.open("test.db")),
orb = FakeORB,
}
local user = assert(logins:newLogin("user", key))
local obs = assert(user:newObserver(logins.orb:newproxy("obs", nil, "IObserver")))
assert(os.execute("chmod 000 test.db/Logins"))
obs:watchLogin(user)
assertIterator({[obs] = true}, user:iObservers())
assertIterator({[user.id] = true}, obs:iWatchedLoginIds())
assert(os.execute("chmod 000 test.db/LoginObservers"))
assertEx("unable to .- file 'test%.db/LoginObservers/[%x-]+%.lua' %(.-: Permission denied%)",
obs.forgetLogin, obs, user)
assertIterator({[obs] = true}, user:iWatchers())
assertIterator({[user.id] = true}, obs:iWatchedLoginIds())
assertEx("unable to .- file 'test%.db/Logins/[%x-]+%.lua%.tmp' %(.-: Permission denied%)",
logins.newLogin, logins, "fail")
assertIterator({[user.id] = user}, logins:iLogins())
assertEx("unable to .- file 'test%.db/LoginObservers/[%x-]+%.lua' %(.-: Permission denied%)",
user.remove, user)
assert(logins:getLogin(user.id) == user)
assert(logins:getObserver(obs.id) == obs)
assertIterator({[obs.id] = obs}, logins:iObservers())
assertIterator({[user.id] = user}, logins:iLogins())
assertIterator({[obs] = true}, user:iObservers())
assert(os.execute("chmod 755 test.db/LoginObservers"))
obs:forgetLogin(user)
for _ in user:iWatchers() do error("failure") end
for _ in obs:iWatchedLoginIds() do error("failure") end
assert(os.execute("chmod 755 test.db/Logins"))
user:remove()
assert(logins:getLogin(user.id) == nil)
assert(logins:getObserver(obs.id) == nil)
for _ in logins:iObservers() do error("failure") end
for _ in logins:iLogins() do error("failure") end
end
do
local lfs = require "lfs"
assert(lfs.rmdir("test.db/Logins"))
assert(lfs.rmdir("test.db/LoginObservers"))
assert(lfs.rmdir("test.db"))
assert(os.remove("test.db"))
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment