Skip to content

Commit

Permalink
v1 (technically v1.1.0 but who cares)
Browse files Browse the repository at this point in the history
  • Loading branch information
DaInfLoop committed Oct 8, 2023
1 parent 0c7f595 commit ccab66a
Show file tree
Hide file tree
Showing 7 changed files with 490 additions and 146 deletions.
105 changes: 80 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,73 +1,128 @@
# repl-auth
# replace-replit

Use Replit's Repl Auth in your project without hosting on Replit.
Use some of Replit's features in your project without hosting on Replit.

## Usage

### Replit
### ReplAuth

Use this exactly how you'd use [`@replit/repl-auth`](https://npm.im/@replit/repl-auth):
The ReplAuth module only supports express and socket.io currently.

```js
import { getUserInfo } from "repl-auth";
import { auth } from "replace-replit";
import express from "express";
import { createServer } from 'node:http';
import { Server } from 'socket.io';

const app = express();
const server = createServer(app);
const io = new Server(server);
app.use(auth.express());

app.get('/', (req, res) => {
const user = getUserInfo(req);
const username = req.get("X-Replit-User-Name");

if (user)
res.send(`Hello, ${user.name}!`);
if (username)
res.send(`Hello, ${username}!`);
else
res.send(`Hello, World!`);
});

app.listen(8000, () => {
io.use(auth.socketIo({ exposeAs: "user" }))

io.on('connection', (socket) => {
console.log('connection from', socket.user.name)
})

server.listen(8000, () => {
console.log("App is running on port 8000");
});
```

### Anywhere else
### ReplDB

The module only supports express currently.
The ReplDB module only supports express and socket.io currently.

```js
import { express as replAuth } from "repl-auth";
// server.js
import { db } from "replace-replit";
import express from "express";

const app = express();
app.use(replAuth());

app.get('/', (req, res) => {
const username = req.get("X-Replit-User-Name");

if (username)
res.send(`Hello, ${username}!`);
else
res.send(`Hello, World!`);
});
app.use(db.express({
file: "database.json",
fileType: "json"
}));

app.listen(8000, () => {
console.log("App is running on port 8000");
});

// test.js
import Database from "@replit/database";

const db = new Database("localhost:8000");

await db.set("hello", "world")

await db.get("hello") // world
```

## Options

Currently there is only one option passable to the `replAuth` middleware:
### ReplAuth
Currently there is only one option passable to the `auth` middleware:

`exposeAs` will allow you to control what an object containing the user data will be set to:

```js
app.use(replAuth({ exposeAs: "user" }))
app.use(auth.express({ exposeAs: "user" }))

// In a route handler...
req.user.name // contains the user's username
```

### ReplDB
There are 4 options passable to the `db` middleware:

`file`: Controls what file your database will be saved to.
`fileType`: Controls what type your file will use. Values can either be `json`, `toml`, `ini`, or `custom` (see below):

`parse`: Function that takes two arguments, data (the file contents) and fileType (the fileType passed to the middleware).

```js
db.express({
// ...
parse(data, fileType) {
if (fileType == "...") {
// do stuff
return TheResultingDataInAnObject
} else {
throw new Error('i dunno what this file type is')
}
}
})
```

`stringify`: Function that takes two arguments, data (the current db object) and fileType (the fileType passed to the middleware).

```js
db.express({
// ...
stringify(data, fileType) {
if (fileType == "...") {
// do stuff
return TheResultingDataInAString
} else {
throw new Error('i dunno what this file type is')
}
}
})
```

# Acknowledgements

[PotentialStyx](https://replit.com/@PotentialStyx) - Helped me with verifying the JWT
[PikachuB2005](https://replit.com/@PikachuB2005) - Donated the package name to me
[PikachuB2005](https://replit.com/@PikachuB2005) - Donated the package name to me
[coding398](https://replit.com/@codingMASTER398) - Cool tester + has great ideas + bug fixer
[DillonB07](https://replit.com/@DillonB07) - Helped on the README
12 changes: 8 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "repl-auth",
"version": "1.0.10",
"description": "Use Replit's Repl Auth in your project without hosting on Replit.",
"name": "replace-replit",
"version": "1.0.0",
"description": "Use some of Replit's features in your project without hosting on Replit.",
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
Expand Down Expand Up @@ -38,6 +38,7 @@
"@babel/preset-env": "^7.16.0",
"@rollup/plugin-babel": "^5.3.0",
"@rollup/plugin-commonjs": "^21.0.1",
"@rollup/plugin-json": "^6.0.1",
"@rollup/plugin-node-resolve": "^13.0.6",
"@rollup/plugin-typescript": "^8.3.3",
"@types/express": "^4.17.17",
Expand All @@ -61,9 +62,12 @@
"typescript": "^4.7.3"
},
"dependencies": {
"@iarna/toml": "^2.2.5",
"@replit/repl-auth": "^1.0.0",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.1"
"ini": "^4.1.1",
"jsonwebtoken": "^9.0.1",
"socket.io": "^4.7.2"
},
"directories": {
"test": "tests"
Expand Down
2 changes: 2 additions & 0 deletions rollup.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const typescript = require('@rollup/plugin-typescript');
const { babel } = require('@rollup/plugin-babel');
const { nodeResolve: resolve } = require('@rollup/plugin-node-resolve');
const commonjs = require('@rollup/plugin-commonjs');
const json = require('@rollup/plugin-json');
const { terser } = require('rollup-plugin-terser');
const dts = require('rollup-plugin-dts').default;
const del = require('rollup-plugin-delete');
Expand Down Expand Up @@ -32,6 +33,7 @@ module.exports = [
}),
resolve(),
commonjs(),
json(),

/* Optionally uncomment the line below
to minify the final bundle: */
Expand Down
115 changes: 2 additions & 113 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,113 +1,2 @@
import type { Request, Response, NextFunction } from 'express';
import { verify } from 'jsonwebtoken';

const PUBKEY = `-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEv+0QT2+9KdAHZMXROxnLmfE9qkry
1W4bieh/LIyXyl9v2aexV8hef2iMaYmjz9yji2Iae1/sgiywvwflRD5O9Q==
-----END PUBLIC KEY-----
`;

export type Options = {
exposeAs?: string;
};

export function express(
opts?: Options,
): (req: Request, res: Response, next: NextFunction) => void {
return function middleware(
req: Request,
res: Response,
next: NextFunction,
) {
if (req.path == '/__replauth') {
const REPL_AUTH = req.query.token as string;

let user;

try {
user = verify(REPL_AUTH, PUBKEY);
} catch (err) {
return res.status(400).send('bad jwt');
}

return res
.cookie('REPL_AUTH', REPL_AUTH)
.status(304)
.redirect(req.query.redirect);
} else if (req.path == '/__replauthuser') {
const cookies: { [key: string]: string } = Object.fromEntries(
req.headers.cookie.split(';').map((x) => {
const a = x.trim().split('=');
return [a.shift(), a.join('=')];
}),
);

const REPL_AUTH = cookies.REPL_AUTH;

let user;

try {
user = verify(REPL_AUTH, PUBKEY);
} catch (err) {
return res.send('User is not logged in');
}

return res.json({
id: user.sub,
name: user.name,
bio: user.bio,
url: user.url,
profileImage: user.profile_image,
roles: user.roles.split(','),
teams: user.teams.split(','),
});
}

if(!req.headers.cookie){
return next();
}

const cookies: { [key: string]: string } = Object.fromEntries(
req.headers.cookie.split(';').map((x) => {
const a = x.trim().split('=');
return [a.shift(), a.join('=')];
}),
);

if(!cookies.REPL_AUTH) return next();

const REPL_AUTH = cookies.REPL_AUTH;

let user;

try {
user = verify(REPL_AUTH, PUBKEY);
} catch (err) {
return next(err);
}

req.headers['x-replit-user-name'] = user.name;
req.headers['x-replit-user-id'] = user.sub;
req.headers['x-replit-user-bio'] = user.bio;
req.headers['x-replit-user-url'] = user.url;
req.headers['x-replit-user-profile-image'] = user.profile_image;
req.headers['x-replit-user-teams'] = user.teams;
req.headers['x-replit-user-roles'] = user.roles;

if (opts.exposeAs) {
req[opts.exposeAs] = {
id: user.sub,
name: user.name,
bio: user.bio,
url: user.url,
profileImage: user.profile_image,
roles: user.roles.split(','),
teams: user.teams.split(','),
};
}

next();
};
}

export { getUserInfo } from '@replit/repl-auth';
export * as auth from "./replauth";
export * as db from "./repldb";
Loading

0 comments on commit ccab66a

Please sign in to comment.