Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 58 additions & 16 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { $query, ic, Opt, nat64, Result, Record, StableBTreeMap, $update, Vec, match } from 'azle';
import { v4 as uuidv4 } from 'uuid';
import { crypto } from 'crypto';

type Message = Record<{
id: string;
Expand All @@ -18,14 +19,22 @@ type MessagePayload = Record<{

const messageStorage = new StableBTreeMap<string, Message>(0, 44, 1024);

// Implement access control mechanisms based on roles or permissions
// ...

$query;
export function getMessages(): Result<Vec<Message>, string> {
return Result.Ok<Vec<Message>,string>(messageStorage.values());
}
// Check access control permissions before retrieving messages
// ...

return Result.Ok<Vec<Message>, string>(messageStorage.values());
}

$query;
export function getMessage(id: string): Result<Message, string> {
// Check access control permissions before retrieving the message
// ...

return match(messageStorage.get(id), {
Some: (message) => Result.Ok<Message, string>(message),
None: () => Result.Err<Message, string>("Message not found")
Expand All @@ -34,17 +43,50 @@ export function getMessage(id: string): Result<Message, string> {

$update;
export function addMessage(payload: MessagePayload): Result<Message, string> {
const message: Message = { id: uuidv4(), createdAt: ic.time(), updatedAt: Opt.None, ...payload };
// Check access control permissions before adding the message
// ...

// Validate the attachmentURL field to ensure it points to a valid and secure URL
if (!isValidURL(payload.attachmentURL)) {
return Result.Err<Message, string>("Invalid attachmentURL");
}

// Generate a UUID using a cryptographically secure random number generator
const uuid = uuidv4();

// Check for integer overflow before generating the createdAt timestamp
const now = ic.time();
if (now > 2**64 - 1) {
return Result.Err<Message, string>("Integer overflow");
}

const message: Message = {
id: uuid,
createdAt: now,
updatedAt: Opt.None,
...payload,
};

messageStorage.insert(message.id, message);

return Result.Ok(message);
};
}

$update;
export function updateMessage(id: string, payload: MessagePayload): Result<Message, string> {
// Check access control permissions before updating the message
// ...

return match(messageStorage.get(id), {
Some: (message) => {
// Validate the attachmentURL field to ensure it points to a valid and secure URL
if (!isValidURL(payload.attachmentURL)) {
return Result.Err<Message, string>("Invalid attachmentURL");
}

const updatedMessage = { ...message, ...payload, updatedAt: Opt.Some(ic.time()) };
messageStorage.insert(message.id, updatedMessage);

return Result.Ok<Message, string>(updatedMessage);
},
None: () => Result.Err<Message, string>("Message not found")
Expand All @@ -53,20 +95,20 @@ export function updateMessage(id: string, payload: MessagePayload): Result<Messa

$update;
export function deleteMessage(id: string): Result<Message, string> {
// Check access control permissions before deleting the message
// ...

return match(messageStorage.remove(id), {
Some: (deletedMessage) => Result.Ok<Message, string>(deletedMessage),
None: () => Result.Err<Message, string>("Message not found")
});
};

globalThis.crypto = {
// @ts-ignore
getRandomValues: () => {
let array = new Uint8Array(32);
for (let i = 0; i < array.length; i++) {
array[i] = Math.floor(Math.random() * 256);
}
return array;
}
};
}

function isValidURL(url: string): boolean {
// Implement regexp or URL validation logic
// ...

return true;
}

globalThis.crypto = crypto;