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 / \
|
||||
&& 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 /
|
||||
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
|
||||
echo "Couchdb initialization has already completed, skipping"
|
||||
else
|
||||
cp /opt/couchdb/etc/setup.ini /opt/couchdb/etc/local.d/setup.ini
|
||||
# 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
|
||||
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 &
|
||||
COUCHDB_PID=$!
|
||||
|
||||
|
@ -15,16 +16,17 @@ else
|
|||
|
||||
# create couch_peruser required system databases manually on startup
|
||||
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:mysetuppassword 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/_users
|
||||
curl --fail -X PUT -u admin:mysecretpassword http://127.0.0.1:5432/_replicator
|
||||
curl --fail -X PUT -u admin:mysecretpassword http://127.0.0.1:5432/_global_changes
|
||||
echo "system databases created successfully"
|
||||
|
||||
|
||||
# gracefully stop couchdb process
|
||||
echo "killing couchdb process"
|
||||
/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
|
||||
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 {
|
||||
|
||||
//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) {
|
||||
const userIdentifier = localStorage.getItem("current_user")
|
||||
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)=>{
|
||||
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.
|
||||
const remotePouchDb = new PouchDB(this.getRemoteUserDb(localStorage.getItem("current_user")), {skip_setup: true});
|
||||
const session = await remotePouchDb.getSession()
|
||||
const isAuth = !!session?.userCtx?.name
|
||||
const authUser = session?.userCtx?.name
|
||||
const isAuth = !!authUser
|
||||
console.warn("IsAuthenticated? getSession() ====> ", isAuth)
|
||||
|
||||
return isAuth
|
||||
if(!isAuth){
|
||||
return false
|
||||
}
|
||||
//confirm that the logged in user matches the session user
|
||||
return authUser == localStorage.getItem("current_user")
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public Close(): Promise<void> {
|
||||
// Stop remote replication for existing database
|
||||
if(this.replicationHandler){
|
||||
this.replicationHandler.cancel()
|
||||
}
|
||||
return super.Close()
|
||||
}
|
||||
|
||||
|
@ -182,42 +180,25 @@ export class FastenDbService extends PouchdbRepository {
|
|||
console.log("DB createIndex complete", createIndexMsg)
|
||||
|
||||
if(sync){
|
||||
console.log("DB sync init...", userIdentifier, this.getRemoteUserDb(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 );
|
||||
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.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
|
||||
|
||||
|
@ -33,16 +36,28 @@ export function NewRepositiory(userIdentifier?: string, encryptionKey?: string):
|
|||
|
||||
export class PouchdbRepository implements IDatabaseRepository {
|
||||
|
||||
|
||||
replicationHandler: any
|
||||
remotePouchEndpoint: string // "http://localhost:5984"
|
||||
encryptionKey: string
|
||||
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) {
|
||||
this.remotePouchEndpoint = `${globalThis.location.protocol}//${globalThis.location.host}${this.getBasePath()}/database`
|
||||
|
||||
//setup PouchDB Plugins
|
||||
//https://pouchdb.com/guides/mango-queries.html
|
||||
this.localPouchDb = null
|
||||
if(userIdentifier){
|
||||
this.localPouchDb = new PouchDB(userIdentifier);
|
||||
this.encryptionKey = encryptionKey
|
||||
this.enableSync(userIdentifier)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,6 +70,11 @@ export class PouchdbRepository implements IDatabaseRepository {
|
|||
if (!this.localPouchDb) {
|
||||
return;
|
||||
}
|
||||
// Stop remote replication for existing database
|
||||
if(this.replicationHandler){
|
||||
this.replicationHandler.cancel()
|
||||
}
|
||||
|
||||
this.localPouchDb.close();
|
||||
this.localPouchDb = null;
|
||||
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