Skip to content

Commit

Permalink
Merge branch 'master' into nats
Browse files Browse the repository at this point in the history
  • Loading branch information
williamstein committed Jan 18, 2025
2 parents e60daf6 + ed33d8e commit 0a4137f
Show file tree
Hide file tree
Showing 69 changed files with 2,745 additions and 1,293 deletions.
2 changes: 1 addition & 1 deletion src/compute/compute/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,6 @@
"devDependencies": {
"@types/cookie": "^0.6.0",
"@types/node": "^18.16.14",
"typescript": "^5.6.3"
"typescript": "^5.7.3"
}
}
10 changes: 5 additions & 5 deletions src/compute/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 20 additions & 7 deletions src/packages/backend/sha1.test.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
import { sha1, uuidsha1 } from "./sha1";

const cocalc = "CoCalc";
const hash = "c898c97dca68742a5a6331f9fa0ca02483cbfd25";
const uuid = "c898c97d-ca68-4742-a5a6-331f9fa0ca02";

describe("compute some sha1 hashes", () => {
it("computes sha1 hash of old SageMathCloud", () => {
// This is mainly for long term backwards compatibility
it("SageMathCloud/string", () => {
expect(sha1("SageMathCloud")).toBe(
"31acd8ca91346abcf6a49d2b1d88333f439d57a6"
"31acd8ca91346abcf6a49d2b1d88333f439d57a6",
);
});

it("computes sha1 hash of new CoCalc", () => {
expect(sha1("CoCalc")).toBe("c898c97dca68742a5a6331f9fa0ca02483cbfd25");
it("CoCalc/string", () => {
expect(sha1(cocalc)).toBe(hash);
});

it("CoCalc/Buffer", () => {
expect(sha1(Buffer.from(cocalc))).toBe(hash);
});
});

describe("compute some uuids", () => {
it("computes uuid associated to 'CoCalc'", () => {
expect(uuidsha1("CoCalc")).toBe("c898c97d-ca68-4742-a5a6-331f9fa0ca02");
describe("UUIDs", () => {
it("CoCalc/string", () => {
expect(uuidsha1(cocalc)).toBe(uuid);
});

it("CoCalc/Buffer", () => {
expect(uuidsha1(Buffer.from(cocalc))).toBe(uuid);
});
});
18 changes: 12 additions & 6 deletions src/packages/backend/sha1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,20 @@ import { createHash } from "crypto";

// compute sha1 hash of data in hex
export function sha1(data: Buffer | string): string {
const sha1sum = createHash("sha1");

if (typeof data === "string") {
// CRITICAL: Code below assumes data is a Buffer; it will seem to work on a string, but give
// the wrong result where wrong means that it doesn't agree with the frontend version defined
// in misc.
data = Buffer.from(data);
sha1sum.update(data, "utf8");
} else {
// Convert Buffer to Uint8Array
const uint8Array = new Uint8Array(
data.buffer,
data.byteOffset,
data.byteLength,
);
sha1sum.update(uint8Array);
}
const sha1sum = createHash("sha1");
sha1sum.update(data);

return sha1sum.digest("hex");
}

Expand Down
67 changes: 35 additions & 32 deletions src/packages/backend/tcp/enable-messaging-protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Enable two new functions write_mesg and recv_mesg on a TCP socket.
*/

import { Buffer } from "node:buffer";
import { Socket } from "node:net";

import getLogger from "@cocalc/backend/logger";
Expand Down Expand Up @@ -43,54 +44,56 @@ export interface CoCalcSocket extends Socket {
write_mesg: (
type: Type,
mesg: Message,
cb?: (err?: string | Error) => void
cb?: (err?: string | Error) => void,
) => void;
recv_mesg: (opts: RecvMesgOpts) => void;
}

export default function enable(socket: CoCalcSocket, desc: string = "") {
socket.setMaxListeners(500); // we use a lot of listeners for listening for messages

let buf: Buffer | null = null;
let buf: Uint8Array | null = null;
let bufTargetLength = -1;

const listenForMesg = (data: Buffer) => {
buf = buf == null ? data : Buffer.concat([buf, data]);
const listenForMesg = (data: Uint8Array) => {
buf = buf == null ? data : new Uint8Array([...buf, ...data]);
while (true) {
if (bufTargetLength === -1) {
// starting to read a new message
if (buf.length >= 4) {
bufTargetLength = buf.readUInt32BE(0) + 4;
const dv = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
bufTargetLength = dv.getUint32(0) + 4;
} else {
return; // have to wait for more data to find out message length
}
}
if (bufTargetLength <= buf.length) {
// read a new message from our buffer
const type = buf.slice(4, 5).toString();
const type = String.fromCharCode(buf[4]);
const mesg = buf.slice(5, bufTargetLength);

const textDecoder = new TextDecoder();
switch (type) {
case "j": // JSON
const s = mesg.toString();
let obj;
const s = textDecoder.decode(mesg);
try {
// Do not use "obj = JSON.parse(s)"
obj = from_json_socket(s); // this properly parses Date objects
const obj = from_json_socket(s); // this properly parses Date objects
socket.emit("mesg", "json", obj);
} catch (err) {
winston.debug(
`WARNING: failed to parse JSON message='${trunc(
s,
512
)}' on socket ${desc} - ${err}`
512,
)}' on socket ${desc} - ${err}`,
);
// skip it.
return;
}
socket.emit("mesg", "json", obj);
break;
case "b": // BLOB (tagged by a uuid)
socket.emit("mesg", "blob", {
uuid: mesg.slice(0, 36).toString(),
uuid: textDecoder.decode(mesg.slice(0, 36)),
blob: mesg.slice(36),
});
break;
Expand All @@ -117,36 +120,34 @@ export default function enable(socket: CoCalcSocket, desc: string = "") {
socket.write_mesg = (
type: Type,
data: Message,
cb?: (err?: string | Error) => void
cb?: (err?: string | Error) => void,
): void => {
if (data == null) {
// uncomment this to get a traceback to see what might be causing this...
//throw Error(`write_mesg(type='${type}': data must be defined`);
cb?.(`write_mesg(type='${type}': data must be defined`);
return;
}
const send = function (s: string | Buffer): void {
const buf = Buffer.alloc(4);
const send = function (s: string | ArrayBuffer): void {
const length: Uint8Array = new Uint8Array(4);
// This line was 4 hours of work. It is absolutely
// *critical* to change the (possibly a string) s into a
// buffer before computing its length and sending it!!
// Otherwise unicode characters will cause trouble.
if (typeof s === "string") {
s = Buffer.from(s);
}
buf.writeInt32BE(s.length, 0);
if (!socket.writable) {
cb?.("socket not writable");
return;
} else {
socket.write(buf);
}
const data: Uint8Array = new Uint8Array(
typeof s === "string" ? Buffer.from(s) : s,
);

const lengthView = new DataView(length.buffer);
// this was buf.writeInt32BE, i.e. big endian
lengthView.setInt32(0, data.byteLength, false); // false for big-endian

if (!socket.writable) {
cb?.("socket not writable");
return;
} else {
socket.write(s, cb);
socket.write(length);
socket.write(data, cb);
}
};

Expand All @@ -164,11 +165,13 @@ export default function enable(socket: CoCalcSocket, desc: string = "") {
return;
}
send(
Buffer.concat([
Buffer.from("b"),
Buffer.from(data.uuid),
Buffer.from(data.blob),
])
new Uint8Array([
...Buffer.from("b"),
...Buffer.from(data.uuid),
...(Buffer.isBuffer(data.blob)
? data.blob
: Buffer.from(data.blob)),
]).buffer,
);
return;
default:
Expand Down
3 changes: 2 additions & 1 deletion src/packages/frontend/account/public-paths/public-paths.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { Alert, Button, Checkbox, Space, Spin, Table } from "antd";
import { join } from "path";
import { FormattedMessage, useIntl } from "react-intl";

import {
React,
redux,
Expand Down Expand Up @@ -298,7 +299,7 @@ function ComputeImage({ compute_image, project_id, path, setError }) {
<>
<ComputeImageSelector
disabled={saving}
selected_image={selectedImage}
current_image={selectedImage}
layout={"compact"}
onSelect={async (img) => {
setSelectedImage(img);
Expand Down
8 changes: 7 additions & 1 deletion src/packages/frontend/account/ssh-keys/fingerprint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ export function compute_fingerprint(pub: string | undefined): string {
throw new Error("No valid SSH key value");
}
const pubbuffer = Buffer.from(pub, "base64");
const key = md5(pubbuffer);
const key = md5(
new Uint8Array(
pubbuffer.buffer,
pubbuffer.byteOffset,
pubbuffer.byteLength,
),
);
return colons(key);
}
2 changes: 1 addition & 1 deletion src/packages/frontend/app/verify-email-banner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export function VerifyEmail() {
<FormattedMessage
id="app.verify-email-banner.text"
defaultMessage={`{sent, select,
true {Sent! Plesae check your email inbox (maybe spam) and click on the confirmation link.}
true {Sent! Please check your email inbox (and maybe spam) and click on the confirmation link.}
other {Please check and verify your email address: <code>{email}</code>}}`}
values={{
sent,
Expand Down
8 changes: 8 additions & 0 deletions src/packages/frontend/codemirror/css.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
require("codemirror/lib/codemirror.css");
require("codemirror/theme/3024-day.css");
require("codemirror/theme/3024-night.css");
require("codemirror/theme/abbott.css");
require("codemirror/theme/abcdef.css");
//require('codemirror/theme/ambiance-mobile.css') # doesn't highlight python, confusing
require("codemirror/theme/ambiance.css");
require("codemirror/theme/ayu-dark.css");
require("codemirror/theme/ayu-mirage.css");
require("codemirror/theme/base16-dark.css");
require("codemirror/theme/base16-light.css");
require("codemirror/theme/bespin.css");
Expand All @@ -27,9 +30,13 @@ require("codemirror/theme/hopscotch.css");
require("codemirror/theme/icecoder.css");
require("codemirror/theme/idea.css");
require("codemirror/theme/isotope.css");
require("codemirror/theme/juejin.css");
require("codemirror/theme/lesser-dark.css");
require("codemirror/theme/liquibyte.css");
require("codemirror/theme/lucario.css");
require("codemirror/theme/material-darker.css");
require("codemirror/theme/material-ocean.css");
require("codemirror/theme/material-palenight.css");
require("codemirror/theme/material.css");
require("codemirror/theme/mbo.css");
require("codemirror/theme/mdn-like.css");
Expand Down Expand Up @@ -58,6 +65,7 @@ require("codemirror/theme/vibrant-ink.css");
require("codemirror/theme/xq-dark.css");
require("codemirror/theme/xq-light.css");
require("codemirror/theme/yeti.css");
require("codemirror/theme/yonce.css");
require("codemirror/theme/zenburn.css");

require("./mode/mediawiki/mediawiki.css");
Expand Down
3 changes: 2 additions & 1 deletion src/packages/frontend/components/error.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Alert } from "antd";
import { CSSProperties } from "react";
import StaticMarkdown from "@cocalc/frontend/editors/slate/static-markdown";

interface Props {
error: any;
Expand All @@ -23,7 +24,7 @@ export default function ShowError({
type="error"
description={
<div style={{ maxHeight: "150px", overflow: "auto", textWrap: "wrap" }}>
{err}
<StaticMarkdown value={err} />
</div>
}
onClose={() => setError?.("")}
Expand Down
4 changes: 2 additions & 2 deletions src/packages/frontend/components/password.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
This is like Antd's Input.Password but the input does NOT have type='password'
The motivation is that we want to store lots of information in admin config
that is displayed like a password, i.e., hidden by default, but if you have
an input with type='password', then your password manager may aggresively
an input with type='password', then your password manager may aggressively
autofill your password into these fields, thus leaking your personal top
secret password... which is VERY VERY VERY BAD.
If you really are actually creating a react component to enter the usual
password, e.g., a sign in page, then use antd's Input.Password, not this.
NOTE: A huge advantage of this is that we have another component here
NOTE: A huge advantage of this is that we have another component here
PasswordTextArea that works like a multiline text area, but also allows
hiding the input like a password, which is somethign that Input.Password
doesn't provide, as is useful for any secret config that is multiline,
Expand Down
Loading

0 comments on commit 0a4137f

Please sign in to comment.