GitFOSS
.ts
TypeScript
(application/typescript)
// std
import fs from "fs";
// 1st-party
import type { ServiceMethodFactory } from "@ethicdevs/react-monolith";
// generated via script[generate:prisma]
import { User } from "@prisma/client";
// app
import type { UsersServiceDeps } from "./types";

const SSH_RSA_KEY_REGEXP =
  /^ssh-rsa AAAA[0-9A-Za-z+\/]+[=]{0,3} ([^@]+@[^@]+)$/i;

const addUserSSHKey: ServiceMethodFactory<
  UsersServiceDeps,
  [User, string, string],
  Promise<boolean>
> = ({ request }) => {
  return async (user, name, key) => {
    // 0. Validate key is actually a ssh-rsa key
    if (key.match(SSH_RSA_KEY_REGEXP) == null) {
      throw new Error(
        "Invalid public key. Please provide a valid SSH RSA public key."
      );
    }

    const existingKey = await request.prisma.userSSHKey.findFirst({
      where: {
        key: key,
      },
    });

    // 1. Check if public key is already registered
    if (existingKey != null) {
      throw new Error(
        "Public key is already registered. Please use another one."
      );
    }

    // 2. Add key to database
    const userKey = await request.prisma.userSSHKey.create({
      data: {
        name: name,
        key: key,
        user: {
          connect: {
            id: user.id,
          },
        },
      },
    });

    if (userKey == null) {
      return false;
    }

    let line = "";
    line += `command="ssh_command ${user.username}",`;
    line += "no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ";
    line += `${key}\n`;

    // 3. Add key to authorized_keys
    fs.appendFileSync("/home/git/.ssh/authorized_keys", line, {
      encoding: "utf8",
    });

    return true;
  };
};

export default addUserSSHKey;