@despiegk i had the same problem i wrote some proxy types but its bit hacky and i dont use all functions from api so i didnt need full interface also i restricted their usage to end on first on() or once()
import Gun, { SEA } from "gun";
import 'gun/axe'
import 'gun/sea'
import { IGunConstructorOptions } from "gun/types/options";
import { AckCallback } from "gun/types/types";
type AuthArgs = [username: string, password: string, callback: (data: { err?: string }) => any] | [ pair :SEAPair, callback: (data: { err?: string }) => any]
export interface GunUser<T> {
is?: undefined
recall: (opt?: { sessionStorage: typeof sessionStorage }) => GunUser<T> |AuthenticatedGunUser<T>
auth: (...t: AuthArgs) => GunUser<T> |AuthenticatedGunUser<T>
create: (...t: AuthArgs) => GunUser<T> |AuthenticatedGunUser<T>
}
export interface AuthenticatedGunUser<T >{
is: {
alias: string | SEAPair
epub: string
pub: string
}
get: <TKey extends keyof T>(name: TKey) => AuthenticatedGunUserTree<T, TKey> & Promise<T[TKey]>
leave: () => void
}
type AuthenticatedGunUserTree<T , TKey extends keyof T> = AuthenticatedGunUser<T[TKey]> & GunTree<T,TKey>;
interface GunGet<T> {
get: <TKey extends keyof T>(name: TKey) => GunTree<T ,TKey> & GunGet<T[TKey]> &Promise<T[TKey]>
}
type GunTree<T , TKey extends keyof T> = {
on: (callback:(state:T[TKey], key: TKey) => any) => { off: ()=> void }
once: (callback: (state:T[TKey], key: TKey) => any) => void
put: (state: T[TKey], callback?: AckCallback, options ?: {opt ?: { cert ?: string}} ) => void,
set: (state: T[TKey]) => void,
map: (match?: any) => AuthenticatedGunUserTree<T[TKey], keyof T[TKey]>
}
export function isUserAuthenticated <T>(user : GunUser<T> |AuthenticatedGunUser<T>): user is AuthenticatedGunUser<T>{
return !!user.is
}
interface GunDefinition {
user: <T>() => GunUser<T> | AuthenticatedGunUser<T>,
get: <T,TKey extends keyof T>(name: TKey) => GunTree<T ,TKey> & GunGet<T[TKey]> &Promise<T[TKey]>,
on: (eventName: 'auth', callback: () => any) => { off: ()=> void },
}
const TypedGun = Gun as any as {
(options?: string | string[] | IGunConstructorOptions): GunDefinition;
new (options?: string | string[] | IGunConstructorOptions): GunDefinition;
}
export interface SEAPair{
epriv: string
epub: string
priv: string
pub: string
}
type Authority = SEAPair
export const TypedSEA = SEA as any as {
secret: (epubKey: string, pair: SEAPair) => Promise<string>
pair: () => Promise<SEAPair>
sign: (data:any, pair: SEAPair) => Promise<string>
verify: <T>(data: string, pair: SEAPair | string) => Promise<T | undefined>
encrypt: (data:any, pair: SEAPair | string) => Promise<string>
decrypt: <T>(data:string, pair: SEAPair | string) => Promise<T| undefined>
certify: (user : string | string[]| {pub:string} | {pub:string}[], policies: any, pair: Authority, callback: (cert:string) => any, opt?: { blacklist?: string, expiry?:number }) => Promise<string>
}
just use TypedGun or TypedSEA
@amark. Please implement this Forum as multiple threads initiated by each user, not a single thread currently. It is just a mess. Shift this Forum to reddit, and leave gitter?
@amark how can I change the username or alias for gun.user()?
@amark. I want to implement state management on the Clent-side using gundb. I want to expose only a subset of nodes e.g. gun.get("sessionid") on Client-side. I searched a lot, but still have doubts what if client-side hacking may access full gun graph network using XSS/code-injection. What security measures should I take? Is including SEA library enough security measure?
@amark. I am implementing gundb for a production grade app.
// Clear out localstorage to give Gun a fresh start on every load
localStorage.clear()
// Import Gun as a dependency
import Gun from 'gun'
/
var gun = Gun();
/
const server = require('http').createServer().listen(8080);
const gun = Gun({web: server});
var items = gun.get('items');
$('form').on('submit', function(e){
e.preventDefault();
items.set($('input').val());
$('input').val("");
})
items.map().on(function(item, id){
var li = $('#' + id).get(0) || $('<li>').attr('id', id).appendTo('ul');
if(item){
$(li).text(item);
} else {
$(li).hide();
}
})
Hi,
Sorry if this is a silly question, but I've been going over the docs today and I don't quite understand conceptually how the scopes work. So I think I get how user contexts work with storing data like in the following snippet:
$('#said').on('submit', function(e){
e.preventDefault();
if(!user.is){ return }
user.get('said').set($('#say').val());
$('#say').val("");
});
where the get/set/map methods apply to that users space, but if any endpoint can set data into the global space doesn't that mean that the global data set can be flooded? or is there some logic in the relay servers that I'm not understanding that prevents arbitrary data from being ingested and stored?
thoughts on how i would achieve key pair rotation for users created with user.create
? reading the docs, it seems that gun users are essentially key pairs generated with SEA.pair()
. does this mean i need to keep my own way of mapping usernames/alias to a pair, something like:
SEA.pair(({pair}) => {
gun.get('users').
('@some_username').get('activePublicKey').put(pair.pub)
// use `.activePublicKey` to encrypt, certify, etc.
})
or will (nope that would return a "user already exists" error.) gun.user().create(oldUsername, oldPaassphrase)
automatically update the keys?
gun.get('@newAliasYouWant').set(user)
(where user
is logged in)local = GUN(); gun = GUN(peers);
. Does this help?async
, this would be very mysterious if true. Can you replicate?
@amark , I found something. gun.get("some").get("test")
is not exactly the same as gun.get("some/test")
the first one, obey the reference
/ soul. the second one, it straight up doesn't give a shit about reference
.
meaning using the example on the docs
gun.get('user/ambernadal/husband/name') // will result undefined 😭
gun.get('user').get('ambernadal').get('husband').get('name') // will resut Mark Nadal 💑
I haven't tested with null
value, but my guess is, you can bypass the null value, by directly accessing the node using /
edit : just tested it. Yup, it straight up ignore the null value.