diff --git a/src/api/acts/login.ts b/src/api/acts/login.ts index 7a0615f..8585f06 100644 --- a/src/api/acts/login.ts +++ b/src/api/acts/login.ts @@ -1,14 +1,168 @@ +import { select, count, alias, insert, remove, le, update, minus, eq, and } from "dblang"; +import { outbagURLshort } from "../../server/outbagURL.js"; +import { PERMISSIONS } from "../../server/permissions.js"; +import { getRemote } from "../../server/serverCerts.js"; +import { oConf } from "../../sys/config.js"; +import { sha256, verify } from "../../sys/crypto.js"; +import { accounts, db, signupOTA as signupOTATable } from "../../sys/db.js"; +import { get64, uts } from "../../sys/tools.js"; import { Act, Client, STATE } from "../user.js"; - - -export const dummy:Act = { +export const signup: Act = { state: STATE.no, right: 0, + data: { + name: "name-100", + accountKey: "string" + }, + func: async (client: Client, data: any, aws: (code: string, data: any) => void) => { + let countAlias = alias(count(accounts.accID), "countAlias") as any; + let query = await select([countAlias], accounts) + .query(db, true); + let maxUsers = oConf.get("Settings", "maxUsers"); + let userNum = query[0][countAlias]; + if (maxUsers > -1 && userNum > 0 && userNum >= maxUsers) { + aws("error", "config"); + return; + } + let salt = get64(16); + let req = await insert(accounts.name, accounts.rights, accounts.accountKey, accounts.accountKeySalt) + .add(data.name, userNum == 0 ? PERMISSIONS.ALL : PERMISSIONS.DEFAULT, sha256(salt + data.accountKey)) + .query(db); + if (req.affectedRows > 0) { + let accID = req.insertId; + if (!isNaN(accID)) { + aws("ok", ""); + client.state = STATE.client; + client.accID = accID; + client.name = data.name; + client.server = "localhost"; + } + } else { + client.suspect(); + aws("error", "existence"); + } + } +}; + +export const signupOTA = { + state: STATE.no, + right: 0, + data: { + name: "string-100", + accountKey: "string", + OTA: "string" + }, + func: async (client: Client, data: any, aws: (code: string, data: any) => void) => { + // TODO: make transaktion when posible + await remove(signupOTATable) + .where(le(signupOTATable.expires, uts())) + .query(db); + let query = await update(signupOTATable) + .set(signupOTATable.usesLeft, minus(signupOTATable.usesLeft, 1)) + .query(db); + await remove(signupOTATable) + .where(eq(signupOTATable.usesLeft, 0)) + .query(db); + if (query.affectedRows == 0) { + return void aws("error", "ota"); + } + let salt = get64(16); + let req = await insert(accounts.name, accounts.rights, accounts.accountKey, accounts.accountKeySalt) + .add(data.name, PERMISSIONS.DEFAULT, sha256(salt + data.accountKey)) + .query(db); + if (req.affectedRows > 0) { + let accID = req.insertId; + if (!isNaN(accID)) { + aws("ok", ""); + client.state = STATE.client; + client.accID = accID; + client.name = data.name; + client.server = "localhost"; + } + } else { + client.suspect(); + aws("error", "existence"); + } + } +}; + +export const signin = { + state: STATE.no, + right: 0, + data: { + name: "string", + accountKey: "string" + }, + func: async (client: Client, data: any, aws: (code: string, data: any) => void) => { + let query = await select([accounts.accID, accounts.accountKey, accounts.accountKeySalt], accounts) + .where(and( + eq(accounts.name, data.name), + eq(accounts.deleted, 0) + )) + .query(db); + if (query.length == 0 || query[0].accountKey != sha256((query[0].accountKeySalt ?? '') + data.accountKey)) { + client.suspect(); + aws("error", "auth"); + return; + } + var accID = query[0].ID; + if (!isNaN(accID)) { + aws("ok", ""); + client.state = STATE.client; + client.accID = accID; + client.name = data.name; + client.server = "localhost"; + } + } +}; + +export const remote1 = { + state: STATE.no, + right: 0, + data: { + name: "string", + server: "string", + key: "string", + sign: "string", + }, + func: async (client: Client, data: any, aws: (code: string, data: any) => void) => { + data.server = await outbagURLshort(data.server); + try{ + var cert = await getRemote(data.server); + var tagAcert = data.name + "@" + data.server + "-" + data.key; + if (!(await verify(tagAcert, data.sign, cert))) { + client.suspect(); + aws("error", "signature"); + return; + } + + client.name = data.name; + client.server = data.server; + client.challenge = get64(64); + client.state = STATE.remoteP; + client.remoteKey = data.key; + aws("ok", client.challenge); + }catch (e){ + client.suspect(); + aws("error","signature"); + } + } +}; + +export const remote2 = { + state: STATE.remoteP, + right: 0, data: { sign: "string" }, - func: async (client: Client, data, aws) => { - aws("ok","dummy"); + func: async (client: Client, data: any, aws: (code: string, data: any) => void) => { + if(await verify(client.challenge,data.sign,client.remoteKey)){ + aws("ok", ""); + client.state = STATE.remote; + }else{ + client.suspect(); + aws("error", "signature"); + } } }; \ No newline at end of file diff --git a/src/api/user.ts b/src/api/user.ts index 5c31735..5f68bef 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -31,6 +31,8 @@ export class Client { state: number = STATE.no; accID: number = -1; + challenge: string = ""; + remoteKey: string = ""; constructor(ip: string) { this.ip = ip;