Compare commits

...

4 Commits

@ -1,25 +1,32 @@
import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:ffi'; import 'dart:ffi';
import 'dart:io'; import 'dart:io';
import 'package:postgres/postgres.dart'; import 'package:postgres/postgres.dart';
/* 🟥 🟧 🟨 🟩 🟦 🟪 🟫 ⬛ ⬜ */
class AccountsToPostgres { class AccountsToPostgres {
/* Dev Coco */ static final connection = PostgreSQLConnection("localhost", 5432, 'passworld',
// static final connection = PostgreSQLConnection("localhost", 5432, 'passworld', username: 'pass', password: '1p2a3s4s5');
// username: 'pass', password: '1p2a3s4s5');
/* Dev RemRem */ /* Dev RemRem */
// static final connection = PostgreSQLConnection("localhost", 5432, 'passworld', // static final connection = PostgreSQLConnection("localhost", 5432, 'passworld',
// username: 'hel', password: ''); // username: 'hel', password: '');
/* Error severity:
- error : no user
- unknown : DB logic problem
*/
/* Production */ /* Production */
static final connection = PostgreSQLConnection( /*static final connection = PostgreSQLConnection(
Platform.environment["DB_SERVER"]!, Platform.environment["DB_SERVER"]!,
5432, 5432,
Platform.environment["DB_DATABASE"]!, Platform.environment["DB_DATABASE"]!,
username: Platform.environment["DB_USER"], username: Platform.environment["DB_USER"],
password: Platform.environment["DB_PASSWORD"]); password: Platform.environment["DB_PASSWORD"]);
*/
AccountsToPostgres() { AccountsToPostgres() {
//initConnection(); //initConnection();
} }
@ -36,82 +43,152 @@ class AccountsToPostgres {
}); });
} }
// Create tables and other things for the database
static Future<void> createAccountTable() async { static Future<void> createAccountTable() async {
await openConnection(); await openConnection();
await connection await connection.query("""
.query( CREATE TABLE IF NOT EXISTS \"Account\"(
"CREATE TABLE IF NOT EXISTS \"Account\"(id TEXT PRIMARY KEY,hash TEXT NOT NULL,salt TEXT NOT NULL,twofa VARCHAR(50)[],passwords INTEGER[])") id INT PRIMARY KEY,
.then((value) { mail TEXT NOT NULL UNIQUE,
print("🟦 Account Table Created"); hash TEXT NOT NULL,
}); salt TEXT NOT NULL,
twofa VARCHAR(50)[],
password_file INTEGER[]
)""");
await connection.query("""
CREATE SEQUENCE IF NOT EXISTS plus1id
INCREMENT 1
START 1""");
print("🟦 Account Table Created");
await initLogs();
} }
// Add support for twoFa if needed // Create user account
static Future<void> create(String email, String hash, static Future<void> createAccount(
String salt /*, List<String> twoFaStr*/) async { String mail, String hash, String salt) async {
await connection.query("INSERT INTO \"Account\" VALUES(@id,@hash,@salt)", await connection.query(
substitutionValues: { "INSERT INTO \"Account\" VALUES(nextval('plus1id'),@mail,@hash,@salt)",
"id": email, substitutionValues: {"mail": mail, "hash": hash, "salt": salt});
"hash": hash,
"salt": salt /*,
"twofa": twoFaStr*/
});
print("✅ Account succesfully created");
} }
static Future<String> selectHashById(String id) async { // get user passord hash by mail
static Future<String> selectHashByMail(String mail) async {
List<List<dynamic>> results = await connection.query( List<List<dynamic>> results = await connection.query(
"SELECT hash FROM \"Account\" WHERE id=@identifiant", "SELECT hash FROM \"Account\" WHERE mail=@mail",
substitutionValues: {"mail": mail});
if (results.length < 1) {
throw PostgreSQLException("No user for this id",
severity: PostgreSQLSeverity.error);
}
if (results.length > 1) {
throw PostgreSQLException("WARNING ! : multiple user with this id",
severity: PostgreSQLSeverity.unknown);
}
return results[0][0];
}
// check if mail is already used in database
static Future<String> selectMailByMail(String mail) async {
List<List<dynamic>> results = await connection.query(
"SELECT mail FROM \"Account\" WHERE mail=@mail",
substitutionValues: {"mail": mail});
return results[0][0];
}
static Future<List<Int>> selectPassFileById(String id) async {
List<List<dynamic>> results = await connection.query(
"SELECT passwords FROM \"Account\" WHERE id=@identifiant",
substitutionValues: {"identifiant": id}); substitutionValues: {"identifiant": id});
closeConnection(); if (results.length < 1) {
throw PostgreSQLException("No user for this id",
severity: PostgreSQLSeverity.error);
}
if (results.length > 1) {
throw PostgreSQLException("WARNING ! : multiple user with this id",
severity: PostgreSQLSeverity.unknown);
}
return results[0][0]; return results[0][0];
} }
static Future<void> updatePass( // Update user password
String identifiant, String hash, String salt) async { static Future<void> updatePassword(
if (selectHashById(identifiant) == null) { String mail, String newHash, String newSalt) async {
if (selectHashByMail(mail) == null) {
return; return;
} else { } else {
await connection.query( await connection.query(
"UPDATE \"Account\" SET hash=@h, salt=@s WHERE id=@identifiant", "UPDATE \"Account\" SET hash=@newHash and salt=@salt WHERE mail=@mail",
substitutionValues: { substitutionValues: {
"identifiant": identifiant, "mail": mail,
"h": hash, "newHash": newHash,
"s": salt "newSalt": newSalt
}); });
print("✅ Passworld succesfully updated");
} }
} }
static Future<void> updateFilePass( // Update user password file
String identifiant, File passwordFile) async { static Future<void> updatePasswordFile(String mail, File passwordFile) async {
List<int> passwordBlob = List<int> passwordBlob =
utf8.encode(await passwordFile.readAsString(encoding: utf8)); utf8.encode(await passwordFile.readAsString(encoding: utf8));
if (selectHashById(identifiant) == null) { if (selectHashByMail(mail) == null) {
return; return;
} else { } else {
await connection.query( await connection.query(
"UPDATE \"Account\" SET passwords=@p WHERE id=@identifiant", "UPDATE \"Account\" SET passwords=@p WHERE id=@identifiant",
substitutionValues: {"identifiant": identifiant, "p": passwordBlob}); substitutionValues: {"identifiant": mail, "p": passwordBlob});
} }
} }
static Future<void> updateTwoFa(String identifiant, List<String> tfa) async { // Update user twoFa
static Future<void> updateTwoFa(String mail, List<String> tfa) async {
List<String> twoFaStr = List.empty(growable: true); List<String> twoFaStr = List.empty(growable: true);
if (selectHashById(identifiant) == null) { if (selectHashByMail(mail) == null) {
return; return;
} else { } else {
await connection.query( await connection.query(
"UPDATE \"Account\" SET twofa=@tfa WHERE id=@identifiant", "UPDATE \"Account\" SET twofa=@tfa WHERE id=@identifiant",
substitutionValues: {"identifiant": identifiant, "tfa": tfa}); substitutionValues: {"identifiant": mail, "tfa": tfa});
} }
} }
static Future<void> deleteById(String id) async { static Future<void> deleteAccount(String mail) async {
await connection.query("DELETE FROM \"Account\" WHERE id=@identifiant", var deletion = 1;
substitutionValues: {"identifiant": id}); await connection.query("DELETE FROM \"Account\" WHERE mail=@mail",
substitutionValues: {"mail": mail});
try {
selectHashByMail(mail);
} on PostgreSQLException catch (e) {
if (e.severity == PostgreSQLSeverity.error) {
deletion = 0;
}
}
if (deletion == 1) {
throw PostgreSQLException("User not deleted",
severity: PostgreSQLSeverity.unknown);
}
}
// Update user mail
static Future<void> updateMail(String mail, String newMail) async {
if (selectHashByMail(mail) == null) {
return;
} else {
await connection.query(
"UPDATE \"Account\" SET mail=@newMail WHERE mail=@mail",
substitutionValues: {"newMail": newMail, "mail": mail});
print("✅ Mail succesfully updated");
}
} }
// //
@ -124,4 +201,77 @@ class AccountsToPostgres {
print("🟥 ADMIN: get all users"); print("🟥 ADMIN: get all users");
return res; return res;
} }
static Future<void> flushUsers() async {
await connection.query("DELETE FROM \"Account\" ");
List<List<dynamic>> rows =
await connection.query("SELECT COUNT(*) FROM \"Account\" ");
if (rows[0][0] != 0) {
throw PostgreSQLException("Flush of users did not succeed",
severity: PostgreSQLSeverity.unknown);
}
print("🟥 ADMIN: all users deleted");
}
static Future<void> flushTable() async {
await connection.query("DROP TABLE \"Account\" ");
try {
await connection.query("SELECT * FROM \"Account\" ");
throw PostgreSQLException('Table Not dropped',
severity: PostgreSQLSeverity.unknown);
} on PostgreSQLException {
print("🟥 ADMIN: tables droped");
}
}
static Future<void> createLogsTable() async {
await connection
.query(
"CREATE TABLE IF NOT EXISTS Log(wwhen TIMESTAMP,wwho char(20),whow char(20),wwhat varchar(800));")
.then((value) {
print("⬜ ADMIN: Logs table created");
});
}
static Future<void> createLogingFunction() async {
await connection
.query(
"CREATE OR REPLACE FUNCTION log()RETURNS TRIGGER AS \$\$ BEGIN IF(TG_OP='DELETE')THEN INSERT INTO Log VALUES(CURRENT_TIMESTAMP,current_role,TG_OP,OLD.id||' '||OLD.hash||' '||OLD.salt); RETURN OLD; ELSEIF(TG_OP='INSERT')THEN INSERT INTO Log VALUES(CURRENT_TIMESTAMP,current_role,TG_OP,NEW.id||' '||NEW.hash||' '||NEW.salt);RETURN NEW; ELSE INSERT INTO Log VALUES(CURRENT_TIMESTAMP,current_role,TG_OP,OLD.id||' '||OLD.hash||' '||OLD.salt||' => '||NEW.id||' '||NEW.hash||' '||NEW.salt); RETURN NEW; END IF; END; \$\$ LANGUAGE plpgsql;")
.then((value) {
print("⬜ ADMIN: Logs function created");
});
}
static Future<void> createTriggerLogs() async {
await connection
.query(
"CREATE TRIGGER trace_delete BEFORE DELETE OR INSERT OR UPDATE ON \"Account\" FOR EACH ROW EXECUTE FUNCTION log ();")
.then((value) {
print("⬜ ADMIN: Logs trigger created");
});
}
static Future<void> dropTrggerLogs() async {
await connection
.query("DROP Trigger trace_delete ON \"Account\" ")
.then((value) {
print("⬛ ADMIN: Logs trigger dropped");
});
}
static Future<void> flushLogs() async {
await connection.query("DELETE FROM Log").then((value) {
print("⬛ ADMIN: Logs flushed");
});
}
static Future<void> initLogs() async {
await createLogsTable();
await createLogingFunction();
createTriggerLogs();
}
} }

@ -0,0 +1,12 @@
import 'dart:io';
import 'package:passworld_api/database/accounts_to_postgres.dart';
import 'package:postgres/postgres.dart';
void main()async{
await AccountsToPostgres.openConnection();
await AccountsToPostgres.flushUsers();
await AccountsToPostgres.flushTable();
AccountsToPostgres.closeConnection();
}
Loading…
Cancel
Save