parent
981fcfbc7b
commit
2e21176ad7
|
@ -9,7 +9,7 @@ RUN curl https://github.com/just-containers/s6-overlay/releases/download/v1.21.8
|
||||||
&& tar xzf /tmp/s6-overlay-${S6_ARCH}.tar.gz -C / \
|
&& tar xzf /tmp/s6-overlay-${S6_ARCH}.tar.gz -C / \
|
||||||
&& rm -rf /tmp/s6-overlay-${S6_ARCH}.tar.gz
|
&& rm -rf /tmp/s6-overlay-${S6_ARCH}.tar.gz
|
||||||
|
|
||||||
COPY /docker/couchdb/local.ini /opt/couchdb/etc/
|
COPY /docker/couchdb/local.ini /opt/couchdb/etc/local.ini
|
||||||
COPY /docker/rootfs /
|
COPY /docker/rootfs /
|
||||||
RUN rm -rf /etc/services.d/fasten #delete the fasten app from the couchdbase container.
|
RUN rm -rf /etc/services.d/fasten #delete the fasten app from the couchdbase container.
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,11 @@
|
||||||
if [ -f "/opt/couchdb/data/.init_complete" ]; then
|
if [ -f "/opt/couchdb/data/.init_complete" ]; then
|
||||||
echo "Couchdb initialization has already completed, skipping"
|
echo "Couchdb initialization has already completed, skipping"
|
||||||
else
|
else
|
||||||
cp /opt/couchdb/etc/setup.ini /opt/couchdb/etc/local.d/setup.ini
|
|
||||||
# start couchdb as a background process (store PID)
|
# start couchdb as a background process (store PID)
|
||||||
echo "Couchdb initialization: start couchdb in background mode"
|
echo "Couchdb initialization: start couchdb in background mode (non-standard port)"
|
||||||
# https://linux.die.net/man/1/couchdb
|
# https://linux.die.net/man/1/couchdb
|
||||||
|
sed -i -e 's/;port = 5984/port = 5432/g' /opt/couchdb/etc/local.ini
|
||||||
|
sed -i -e 's/bind_address = 0.0.0.0/bind_address = 127.0.0.1/g' /opt/couchdb/etc/local.ini
|
||||||
/opt/couchdb/bin/couchdb -b &
|
/opt/couchdb/bin/couchdb -b &
|
||||||
COUCHDB_PID=$!
|
COUCHDB_PID=$!
|
||||||
|
|
||||||
|
@ -15,16 +16,17 @@ else
|
||||||
|
|
||||||
# create couch_peruser required system databases manually on startup
|
# create couch_peruser required system databases manually on startup
|
||||||
echo "couchdb ready, start creating system databases"
|
echo "couchdb ready, start creating system databases"
|
||||||
curl --fail -X PUT -u admin:mysetuppassword http://127.0.0.1:5432/_users
|
curl --fail -X PUT -u admin:mysecretpassword http://127.0.0.1:5432/_users
|
||||||
curl --fail -X PUT -u admin:mysetuppassword http://127.0.0.1:5432/_replicator
|
curl --fail -X PUT -u admin:mysecretpassword http://127.0.0.1:5432/_replicator
|
||||||
curl --fail -X PUT -u admin:mysetuppassword http://127.0.0.1:5432/_global_changes
|
curl --fail -X PUT -u admin:mysecretpassword http://127.0.0.1:5432/_global_changes
|
||||||
echo "system databases created successfully"
|
echo "system databases created successfully"
|
||||||
|
|
||||||
|
|
||||||
# gracefully stop couchdb process
|
# gracefully stop couchdb process
|
||||||
echo "killing couchdb process"
|
echo "killing couchdb process"
|
||||||
/opt/couchdb/bin/couchdb -k
|
/opt/couchdb/bin/couchdb -k
|
||||||
rm -f /opt/couchdb/etc/local.d/setup.ini
|
|
||||||
|
sed -i -e 's/port = 5432/;port = 5984/g' /opt/couchdb/etc/local.ini
|
||||||
|
sed -i -e 's/bind_address = 127.0.0.1/bind_address = 0.0.0.0/g' /opt/couchdb/etc/local.ini
|
||||||
|
|
||||||
# create the init complete flag
|
# create the init complete flag
|
||||||
echo "Couchdb initialization: complete"
|
echo "Couchdb initialization: complete"
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
; CouchDB Configuration Settings
|
|
||||||
|
|
||||||
; This minimal file is only for use during first setup. It is insecure and WILL NOT be used after setup completes
|
|
||||||
; it will be copied into /opt/couchdb/etc/local.d temporarily.
|
|
||||||
[couchdb]
|
|
||||||
single_node = true
|
|
||||||
|
|
||||||
[couch_peruser]
|
|
||||||
enable = true
|
|
||||||
|
|
||||||
[chttpd]
|
|
||||||
; bind to localhost and a non-standard, unexposed port.
|
|
||||||
port = 5432
|
|
||||||
bind_address = 127.0.0.1
|
|
||||||
|
|
||||||
[admins]
|
|
||||||
; THIS PASSWORD IS INSECURE, it is only used during setup and does not persist.
|
|
||||||
admin = mysetuppassword
|
|
|
@ -25,16 +25,11 @@ PouchDB.plugin(PouchAuth);
|
||||||
})
|
})
|
||||||
export class FastenDbService extends PouchdbRepository {
|
export class FastenDbService extends PouchdbRepository {
|
||||||
|
|
||||||
//TODO: move most of this functionality back into the lib as a separate file.
|
|
||||||
replicationHandler: any
|
|
||||||
remotePouchEndpoint: string // "http://localhost:5984"
|
|
||||||
constructor(private _httpClient: HttpClient) {
|
constructor(private _httpClient: HttpClient) {
|
||||||
const userIdentifier = localStorage.getItem("current_user")
|
const userIdentifier = localStorage.getItem("current_user")
|
||||||
super(userIdentifier, "my-secret-encryption-key");
|
super(userIdentifier, "my-secret-encryption-key");
|
||||||
this.remotePouchEndpoint = `${window.location.protocol}//${window.location.host}${this.getBasePath()}/database`
|
|
||||||
if(userIdentifier){
|
|
||||||
this.enableSync(userIdentifier)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,7 +48,10 @@ export class FastenDbService extends PouchdbRepository {
|
||||||
.then((loginResp)=>{
|
.then((loginResp)=>{
|
||||||
return this.postLoginHook(loginResp.name, true)
|
return this.postLoginHook(loginResp.name, true)
|
||||||
})
|
})
|
||||||
.catch((err) => console.error("an error occurred during login/setup", err))
|
.catch((err) => {
|
||||||
|
console.error("an error occurred during login/setup", err)
|
||||||
|
throw err
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,20 +84,20 @@ export class FastenDbService extends PouchdbRepository {
|
||||||
//if we have a local database, lets see if we have an active session to the remote database.
|
//if we have a local database, lets see if we have an active session to the remote database.
|
||||||
const remotePouchDb = new PouchDB(this.getRemoteUserDb(localStorage.getItem("current_user")), {skip_setup: true});
|
const remotePouchDb = new PouchDB(this.getRemoteUserDb(localStorage.getItem("current_user")), {skip_setup: true});
|
||||||
const session = await remotePouchDb.getSession()
|
const session = await remotePouchDb.getSession()
|
||||||
const isAuth = !!session?.userCtx?.name
|
const authUser = session?.userCtx?.name
|
||||||
|
const isAuth = !!authUser
|
||||||
console.warn("IsAuthenticated? getSession() ====> ", isAuth)
|
console.warn("IsAuthenticated? getSession() ====> ", isAuth)
|
||||||
|
if(!isAuth){
|
||||||
return isAuth
|
return false
|
||||||
|
}
|
||||||
|
//confirm that the logged in user matches the session user
|
||||||
|
return authUser == localStorage.getItem("current_user")
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Close(): Promise<void> {
|
public Close(): Promise<void> {
|
||||||
// Stop remote replication for existing database
|
|
||||||
if(this.replicationHandler){
|
|
||||||
this.replicationHandler.cancel()
|
|
||||||
}
|
|
||||||
return super.Close()
|
return super.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,42 +180,25 @@ export class FastenDbService extends PouchdbRepository {
|
||||||
console.log("DB createIndex complete", createIndexMsg)
|
console.log("DB createIndex complete", createIndexMsg)
|
||||||
|
|
||||||
if(sync){
|
if(sync){
|
||||||
|
console.log("DB sync init...", userIdentifier, this.getRemoteUserDb(userIdentifier))
|
||||||
|
|
||||||
this.enableSync(userIdentifier)
|
this.enableSync(userIdentifier)
|
||||||
|
// .on('paused', function (info) {
|
||||||
|
// // replication was paused, usually because of a lost connection
|
||||||
|
// console.warn("replication was paused, usually because of a lost connection", info)
|
||||||
|
// }).on('active', function (info) {
|
||||||
|
// // replication was resumed
|
||||||
|
// console.warn("replication was resumed", info)
|
||||||
|
// }).on('error', function (err) {
|
||||||
|
// // totally unhandled error (shouldn't happen)
|
||||||
|
// console.error("replication unhandled error (shouldn't happen)", err)
|
||||||
|
// });
|
||||||
|
console.log("DB sync enabled")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.warn( "Configured PouchDB database for,", this.localPouchDb.name );
|
console.warn( "Configured PouchDB database for,", this.localPouchDb.name );
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
private enableSync(userIdentifier: string){
|
|
||||||
console.log("DB sync init...", userIdentifier, this.getRemoteUserDb(userIdentifier))
|
|
||||||
this.replicationHandler = this.localPouchDb.sync(this.getRemoteUserDb(userIdentifier), {live: true, retry: true})
|
|
||||||
.on('paused', function (info) {
|
|
||||||
// replication was paused, usually because of a lost connection
|
|
||||||
console.warn("replication was paused, usually because of a lost connection", info)
|
|
||||||
}).on('active', function (info) {
|
|
||||||
// replication was resumed
|
|
||||||
console.warn("replication was resumed", info)
|
|
||||||
}).on('error', function (err) {
|
|
||||||
// totally unhandled error (shouldn't happen)
|
|
||||||
console.error("replication unhandled error (shouldn't happen)", err)
|
|
||||||
});
|
|
||||||
console.log("DB sync enabled")
|
|
||||||
}
|
|
||||||
|
|
||||||
private getRemoteUserDb(username: string){
|
|
||||||
return `${this.remotePouchEndpoint}/userdb-${this.toHex(username)}`
|
|
||||||
}
|
|
||||||
private toHex(s: string) {
|
|
||||||
// utf8 to latin1
|
|
||||||
s = unescape(encodeURIComponent(s))
|
|
||||||
let h = ''
|
|
||||||
for (let i = 0; i < s.length; i++) {
|
|
||||||
h += s.charCodeAt(i).toString(16)
|
|
||||||
}
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
|
|
||||||
private getBasePath(): string {
|
|
||||||
return window.location.pathname.split('/web').slice(0, 1)[0];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,9 @@ PouchDB.plugin(PouchCrypto);
|
||||||
// PouchDB.plugin(find);
|
// PouchDB.plugin(find);
|
||||||
// PouchDB.debug.enable('pouchdb:find')
|
// PouchDB.debug.enable('pouchdb:find')
|
||||||
|
|
||||||
|
// YOU MUST USE globalThis not window or self.
|
||||||
|
// YOU MUST NOT USE console.* as its not available in a webworker context
|
||||||
|
|
||||||
|
|
||||||
// this is required, otherwise PouchFind fails when looking for the global PouchDB variable
|
// this is required, otherwise PouchFind fails when looking for the global PouchDB variable
|
||||||
|
|
||||||
|
@ -33,16 +36,28 @@ export function NewRepositiory(userIdentifier?: string, encryptionKey?: string):
|
||||||
|
|
||||||
export class PouchdbRepository implements IDatabaseRepository {
|
export class PouchdbRepository implements IDatabaseRepository {
|
||||||
|
|
||||||
|
replicationHandler: any
|
||||||
|
remotePouchEndpoint: string // "http://localhost:5984"
|
||||||
encryptionKey: string
|
encryptionKey: string
|
||||||
localPouchDb: PouchDB.Database
|
localPouchDb: PouchDB.Database
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class can be initialized in 2 states
|
||||||
|
* - unauthenticated
|
||||||
|
* - authenticated - determined using cookie and localStorage.current_user
|
||||||
|
* @param userIdentifier
|
||||||
|
* @param encryptionKey
|
||||||
|
*/
|
||||||
constructor(userIdentifier?: string, encryptionKey?: string) {
|
constructor(userIdentifier?: string, encryptionKey?: string) {
|
||||||
|
this.remotePouchEndpoint = `${globalThis.location.protocol}//${globalThis.location.host}${this.getBasePath()}/database`
|
||||||
|
|
||||||
//setup PouchDB Plugins
|
//setup PouchDB Plugins
|
||||||
//https://pouchdb.com/guides/mango-queries.html
|
//https://pouchdb.com/guides/mango-queries.html
|
||||||
this.localPouchDb = null
|
this.localPouchDb = null
|
||||||
if(userIdentifier){
|
if(userIdentifier){
|
||||||
this.localPouchDb = new PouchDB(userIdentifier);
|
this.localPouchDb = new PouchDB(userIdentifier);
|
||||||
this.encryptionKey = encryptionKey
|
this.encryptionKey = encryptionKey
|
||||||
|
this.enableSync(userIdentifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +70,11 @@ export class PouchdbRepository implements IDatabaseRepository {
|
||||||
if (!this.localPouchDb) {
|
if (!this.localPouchDb) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Stop remote replication for existing database
|
||||||
|
if(this.replicationHandler){
|
||||||
|
this.replicationHandler.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
this.localPouchDb.close();
|
this.localPouchDb.close();
|
||||||
this.localPouchDb = null;
|
this.localPouchDb = null;
|
||||||
return
|
return
|
||||||
|
@ -251,4 +271,31 @@ export class PouchdbRepository implements IDatabaseRepository {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Sync private/protected methods
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
protected getRemoteUserDb(username: string){
|
||||||
|
return `${this.remotePouchEndpoint}/userdb-${this.toHex(username)}`
|
||||||
|
}
|
||||||
|
protected enableSync(userIdentifier: string){
|
||||||
|
return this.replicationHandler = this.localPouchDb.sync(this.getRemoteUserDb(userIdentifier), {live: true, retry: true})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private toHex(s: string) {
|
||||||
|
// utf8 to latin1
|
||||||
|
s = unescape(encodeURIComponent(s))
|
||||||
|
let h = ''
|
||||||
|
for (let i = 0; i < s.length; i++) {
|
||||||
|
h += s.charCodeAt(i).toString(16)
|
||||||
|
}
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Helper methods
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
protected getBasePath(): string {
|
||||||
|
return globalThis.location.pathname.split('/web').slice(0, 1)[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue