Skip to content

Instantly share code, notes, and snippets.

@sloev
Created September 19, 2023 13:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sloev/2039f4c11108f77b4c6aee4138e155ef to your computer and use it in GitHub Desktop.
Save sloev/2039f4c11108f77b4c6aee4138e155ef to your computer and use it in GitHub Desktop.
import crypto from 'crypto'
import GUN from 'gun';
import 'gun/sea.js';
import 'gun/lib/open.js'
import { sha256 } from 'js-sha256';
var SEA = GUN.SEA;
var gun = GUN()
class DB {
constructor() {
this.settings = {
cert: null,
admin_pub: null,
logged_in_user: null
}
this.tables = {
users: null,
messages: null,
sheeps: null,
takens: null,
geohashes: null
}
}
get user() {
return this.settings.logged_in_user
}
get cert() {
return this.settings.cert
}
get adminPub() {
return this.settings.admin_pub
}
randomHash() {
return crypto.randomBytes(16).toString('base64');
}
async create() {
var serverAdmin = await SEA.pair();
await gun.user().auth(serverAdmin);
let rules = [
{ "#": { "*": "users" }, ".": { "+": "*" } },
{ "#": { "*": "messages" }, ".": { "+": "*" } },
{ "#": { "*": "sheeps" }, ".": { "+": "*" } },
{ "#": { "*": "takens" }, ".": { "+": "*" } },
{ "#": { "*": "geohashes" }, ".": { "+": "*" } }
]
var certificate = await SEA.certify("*", rules, serverAdmin, null)
await gun.user(serverAdmin.pub).get("admin").get("cert").put(certificate).then()
return serverAdmin
}
async load(adminPub) {
console.log(this.settings)
this.settings.cert = await gun.user(adminPub).get("admin").get("cert");
this.settings.admin_pub = adminPub;
console.log(this.settings)
for (const table in this.tables) {
this.tables[table] = gun.user(this.settings.admin_pub).get(table)
}
this.tables.root = gun.user(this.settings.admin_pub)
}
async createUser(username, password) {
let existingUser = await this.getUserByUsername(username)
if (existingUser){
throw Error("user already exists")
}
try {
let salt = this.randomHash()
let saltedUsername = username + salt
await new Promise((resolve, reject) => {
gun.user().create(saltedUsername, password, ack => {
if (ack.err) {
reject(ack.err)
} else {
resolve(ack)
}
})
})
await new Promise((resolve, reject) => {
gun.user().auth(saltedUsername, password, ack => {
if (ack.err) {
reject(ack.err)
} else {
resolve(ack)
}
})
})
let userPub = gun.user().is.pub
var user = {
username: username,
salted_username: saltedUsername,
created_at: Date.now(),
pub: userPub
}
this.settings.logged_in_user = user
await this.tables.users.get(username).get(userPub).put(user, null, { opt: { cert: this.cert } }).then()
} catch (e) {
return Error("error creating user:", e)
}
}
async getUserByUsername(username) {
return await new Promise((resolve, reject) => {
const TimerId = setTimeout(() => {
resolve(null) // the requested node seems not to exist (yet)
}, 2000)
this.tables.users.get(username).map().once(data => {
clearTimeout(TimerId)
resolve(data)
}, {wait:0})
})
}
async login(username, password) {
let existingUser = await this.getUserByUsername(username)
if (!existingUser){
throw Error("user doesnt exists")
}
try {
await new Promise((resolve, reject) => {
gun.user().auth(existingUser.salted_username, password, ack => {
if (ack.err) {
reject(ack.err)
} else {
resolve(ack)
}
})
})
var user = {
username: existingUser.username,
salted_username: existingUser.salted_username,
created_at: existingUser.created_at,
pub: existingUser.pub
}
this.settings.logged_in_user = user
} catch (e) {
return Error("auth user error:", e)
}
}
}
export default DB
import DB from './src/helpers/db.mjs';
(async () => {
let db = new DB()
let admin = await db.create()
let err
err = await db.load(admin.pub)
console.log(err)
err = await db.createUser("foobarbas", "foobarbas")
err = await db.login("foobarbas", "foobarbas")
console.log("logged in user", db.user, "err", err)
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment