mirror of
https://github.com/Akif9748/akf-forum.git
synced 2024-11-25 13:00:41 +03:00
Added unauth w/discord, and better auth
This commit is contained in:
parent
43720f0ca0
commit
cf8de73e7c
8 changed files with 130 additions and 90 deletions
|
@ -1,2 +1,3 @@
|
||||||
MONGO_DB_URL = mongodb://localhost:27017/akf-forum
|
MONGO_DB_URL = mongodb://localhost:27017/akf-forum
|
||||||
SECRET = secret
|
SECRET = secret
|
||||||
|
DISCORD_SECRET = yourDiscordSecret
|
43
APIDOCS.md
43
APIDOCS.md
|
@ -67,30 +67,35 @@ You can change them in config.json.
|
||||||
GET ```/api/messages/0```
|
GET ```/api/messages/0```
|
||||||
|
|
||||||
#### Example API Output:
|
#### Example API Output:
|
||||||
```json
|
```js
|
||||||
{
|
{
|
||||||
"_id": "63067429bc01da866fad508b",
|
"react": {
|
||||||
"threadID": "0",
|
"like": [],
|
||||||
"author": {
|
"dislike": ["0"]
|
||||||
"id": "0",
|
|
||||||
"name": "Akif9748",
|
|
||||||
"avatar": "https://cdn.discordapp.com/avatars/539506680140922890/abd74d10aac094fc8a5ad5c86f29fdb9.png?size=1024",
|
|
||||||
"time": "2022-08-24T18:54:55.666Z",
|
|
||||||
"deleted": false,
|
|
||||||
"admin": false,
|
|
||||||
"_id": "630673ffbc01da866fad507b",
|
|
||||||
"__v": 0
|
|
||||||
},
|
},
|
||||||
"content": "deneme",
|
"_id": "6325c216faa938c4cfc43075",
|
||||||
|
"author": {
|
||||||
|
"_id": "632e028ca4ba362ebbb75a43",
|
||||||
|
"name": "Akif9748",
|
||||||
|
"avatar": "/images/avatars/0.jpg",
|
||||||
"deleted": false,
|
"deleted": false,
|
||||||
"edited": false,
|
"edited": true,
|
||||||
"time": "2022-08-24T18:55:37.744Z",
|
"about": "# Owner",
|
||||||
|
"admin": true,
|
||||||
|
"theme": "black",
|
||||||
|
"hideLastSeen": false,
|
||||||
|
"time": "2022-09-23T19:01:32.610Z",
|
||||||
"id": "0",
|
"id": "0",
|
||||||
"__v": 0,
|
"__v": 0,
|
||||||
"react": {
|
"discordID": "539506680140922890"
|
||||||
"like": [0],
|
|
||||||
"dislike": []
|
|
||||||
},
|
},
|
||||||
"authorID": "0"
|
"threadID": "0",
|
||||||
|
"content": "This is a thread opened via API, yes",
|
||||||
|
"deleted": false,
|
||||||
|
"edited": true,
|
||||||
|
"time": "2022-09-17T12:48:22.378Z",
|
||||||
|
"id": "0",
|
||||||
|
"__v": 4,
|
||||||
|
"oldContents": []
|
||||||
}
|
}
|
||||||
```
|
```
|
|
@ -14,6 +14,7 @@ Edit `config.json` for default themes (`black` or `default`) of users, and forum
|
||||||
|
|
||||||
### DISCORD AUTH:
|
### DISCORD AUTH:
|
||||||
`"discord_auth": "your_app_id"` in config.json.
|
`"discord_auth": "your_app_id"` in config.json.
|
||||||
|
Add your app secret to `.env` as `DISCORD_SECRET`.
|
||||||
Create a redirect url in discord developer portal:
|
Create a redirect url in discord developer portal:
|
||||||
`https://forum_url.com/discord_auth/hash`
|
`https://forum_url.com/discord_auth/hash`
|
||||||
|
|
||||||
|
@ -43,7 +44,6 @@ Akf-forum has got an API for AJAX (fetch), other clients etc. And, you can learn
|
||||||
- mod role, permissions
|
- mod role, permissions
|
||||||
- upload other photos, model for it
|
- upload other photos, model for it
|
||||||
- categories page is need a update, thread count in category
|
- categories page is need a update, thread count in category
|
||||||
- DC auth will store code for taking tokens, and create secret model setting
|
|
||||||
- Disable last seen button for web.
|
- Disable last seen button for web.
|
||||||
- email auth.
|
- email auth.
|
||||||
- old contents / titles add to forum interface
|
- old contents / titles add to forum interface
|
||||||
|
|
2
index.js
2
index.js
|
@ -44,7 +44,7 @@ app.use(express.static("public"), express.json(), express.urlencoded({extended:t
|
||||||
);
|
);
|
||||||
|
|
||||||
if (discord_auth)
|
if (discord_auth)
|
||||||
app.set("discord_auth", `https://discord.com/api/oauth2/authorize?client_id=${discord_auth}&redirect_uri=${host}%2Fdiscord_auth%2Fhash&response_type=token&scope=identify`);
|
app.set("discord_auth", `https://discord.com/api/oauth2/authorize?client_id=${discord_auth}&redirect_uri=${host}%2Fauth%2Fdiscord&response_type=code&scope=identify`);
|
||||||
|
|
||||||
if (RLS.enabled) app.use(RL(RLS.windowMs, RLS.max));
|
if (RLS.enabled) app.use(RL(RLS.windowMs, RLS.max));
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,8 @@ const schema = new mongoose.Schema({
|
||||||
lastSeen: { type: Date, default: Date.now, select: false },
|
lastSeen: { type: Date, default: Date.now, select: false },
|
||||||
hideLastSeen: { type: Boolean, default: false },
|
hideLastSeen: { type: Boolean, default: false },
|
||||||
ips: { type: [String], default: [], select: false },
|
ips: { type: [String], default: [], select: false },
|
||||||
password: { type: String, select: false }
|
password: { type: String, select: false },
|
||||||
|
discord_code: { type: String, select: false }
|
||||||
});
|
});
|
||||||
|
|
||||||
schema.methods.takeId = async function () {
|
schema.methods.takeId = async function () {
|
||||||
|
|
87
routes/auth.js
Normal file
87
routes/auth.js
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
const { Router } = require("express")
|
||||||
|
const { UserModel } = require("../models");
|
||||||
|
const fetch = require("node-fetch");
|
||||||
|
const app = Router();
|
||||||
|
const { host, discord_auth } = require("../config.json")
|
||||||
|
|
||||||
|
app.get("/discord", async (req, res) => {
|
||||||
|
const client_id = discord_auth;
|
||||||
|
if (!client_id) return res.error(404, "Discord auth is disabled")
|
||||||
|
const { code } = req.query;
|
||||||
|
if (!code) return res.error(400, "No code provided");
|
||||||
|
try {
|
||||||
|
const response = await fetch('https://discord.com/api/v10/oauth2/token', {
|
||||||
|
method: 'POST',
|
||||||
|
body: new URLSearchParams({
|
||||||
|
client_id, code,
|
||||||
|
client_secret: process.env.DISCORD_SECRET,
|
||||||
|
grant_type: 'authorization_code',
|
||||||
|
redirect_uri: host + "/auth/discord",
|
||||||
|
scope: 'identify',
|
||||||
|
}).toString(),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) return res.error(500, "Bad request to discord");
|
||||||
|
|
||||||
|
const { access_token, token_type } = await response.json();
|
||||||
|
|
||||||
|
const discord = await fetch('https://discord.com/api/users/@me', {
|
||||||
|
headers: { authorization: `${token_type} ${access_token}` }
|
||||||
|
}).then(res => res.json());
|
||||||
|
|
||||||
|
const forum = await UserModel.findOne({ discordID: discord.id });
|
||||||
|
|
||||||
|
if (req.user) {
|
||||||
|
if (req.user.discordID)
|
||||||
|
return res.error(403, "Your forum account is already linked to a discord account.");
|
||||||
|
|
||||||
|
if (forum)
|
||||||
|
return res.error(403, "This discord account is already linked to a forum account.");
|
||||||
|
|
||||||
|
req.user.discordID = discord.id;
|
||||||
|
req.user.discord_code = code;
|
||||||
|
await req.user.save();
|
||||||
|
return res.redirect(`/users/${req.user.id}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (forum) {
|
||||||
|
req.session.userID = forum.id;
|
||||||
|
return res.redirect("/");
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = discord.username + discord.discriminator;
|
||||||
|
while (await UserModel.findOne({ name }))
|
||||||
|
name += Math.floor(Math.random() * 2);
|
||||||
|
|
||||||
|
const user2 = new UserModel({
|
||||||
|
name, discordID: discord.id, discord_code: code,
|
||||||
|
avatar: `https://cdn.discordapp.com/avatars/${discord.id}/${discord.avatar}.png?size=256`
|
||||||
|
});
|
||||||
|
|
||||||
|
await user2.takeId();
|
||||||
|
await user2.save();
|
||||||
|
|
||||||
|
req.session.userID = user2.id;
|
||||||
|
|
||||||
|
res.redirect("/");
|
||||||
|
} catch (error) {
|
||||||
|
res.error(500, "Something went wrong");
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.delete("/discord", async (req, res) => {
|
||||||
|
if (!req.user) return res.error(403, "You are not logged in");
|
||||||
|
if (!req.user.discordID) return res.error(403, "You don't have a discord account linked to your forum account.");
|
||||||
|
req.user.discordID = undefined;
|
||||||
|
req.user.discord_code = undefined;
|
||||||
|
await req.user.save();
|
||||||
|
res.send("Your discord account has been unlinked from your forum account.");
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = app;
|
|
@ -1,61 +0,0 @@
|
||||||
const { Router } = require("express")
|
|
||||||
const { UserModel } = require("../models");
|
|
||||||
const fetch = require("node-fetch");
|
|
||||||
const app = Router();
|
|
||||||
|
|
||||||
app.use(async (req, res, next) =>
|
|
||||||
req.app.get("discord_auth") ? next() : res.error(404,"Discord auth is disabled")
|
|
||||||
)
|
|
||||||
app.get("/hash", (req, res) => res.send('<script>location.href=location.href.replace("#","?").replace("discord_auth/hash","discord_auth");</script>'))
|
|
||||||
|
|
||||||
app.get("/", async (req, res) => {
|
|
||||||
const { access_token, token_type } = req.query;
|
|
||||||
if (!access_token) return;
|
|
||||||
try {
|
|
||||||
const discord = await fetch('https://discord.com/api/users/@me', {
|
|
||||||
headers: { authorization: `${token_type} ${access_token}` }
|
|
||||||
}).then(res => res.json());
|
|
||||||
|
|
||||||
const forum = await UserModel.findOne({ discordID: discord.id });
|
|
||||||
|
|
||||||
|
|
||||||
if (req.user) {
|
|
||||||
if (req.user.discordID)
|
|
||||||
return res.error(403, "Your forum account is already linked to a discord account.");
|
|
||||||
|
|
||||||
if (forum)
|
|
||||||
return res.error(403, "This discord account is already linked to a forum account.");
|
|
||||||
|
|
||||||
req.user.discordID = discord.id;
|
|
||||||
await req.user.save();
|
|
||||||
return res.send("Your discord account has been linked to your forum account.");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (forum) {
|
|
||||||
req.session.userID = forum.id;
|
|
||||||
return res.redirect("/");
|
|
||||||
}
|
|
||||||
|
|
||||||
let name = discord.username + discord.discriminator;
|
|
||||||
while (await UserModel.findOne({ name }))
|
|
||||||
name += Math.floor(Math.random() * 2);
|
|
||||||
|
|
||||||
const user2 = new UserModel({
|
|
||||||
name, discordID: discord.id,
|
|
||||||
avatar: `https://cdn.discordapp.com/avatars/${discord.id}/${discord.avatar}.png?size=256`
|
|
||||||
});
|
|
||||||
|
|
||||||
await user2.takeId();
|
|
||||||
await user2.save();
|
|
||||||
|
|
||||||
req.session.userID = user2.id;
|
|
||||||
|
|
||||||
res.redirect("/");
|
|
||||||
} catch (error) {
|
|
||||||
res.error(500, "Something went wrong");
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = app;
|
|
|
@ -14,7 +14,9 @@
|
||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<% if (!member.discordID && discord && user?.id === member.id) { %>
|
<% if (!member.discordID && discord && user?.id === member.id) { %>
|
||||||
<a href="<%=discord%>" class="btn-outline-primary">Login with discord</a>
|
<a href="<%=discord%>" class="btn-outline-primary">Auth with discord</a>
|
||||||
|
<% } else if(member.discordID && user?.id === member.id) { %>
|
||||||
|
<a class="btn-outline-primary" id="un_discord">Unauth with discord!</a>
|
||||||
<% } %>
|
<% } %>
|
||||||
<% if (user?.admin || user?.id === member.id) { %>
|
<% if (user?.admin || user?.id === member.id) { %>
|
||||||
<a href="/users/<%=member.id%>/avatar" class="btn-outline-primary">Upload avatar</a>
|
<a href="/users/<%=member.id%>/avatar" class="btn-outline-primary">Upload avatar</a>
|
||||||
|
@ -62,7 +64,12 @@
|
||||||
if (response.deleted) return;
|
if (response.deleted) return;
|
||||||
alert("User is undeleted successfully!");
|
alert("User is undeleted successfully!");
|
||||||
location.reload()
|
location.reload()
|
||||||
} else if (e.target.id == "toogle")
|
} else if (e.target.id == "un_discord") {
|
||||||
|
const response = await fetch("/auth/discord/", {method:"DELETE"});
|
||||||
|
alert(await response.text());
|
||||||
|
location.reload()
|
||||||
|
}
|
||||||
|
else if (e.target.id == "toogle")
|
||||||
document.getElementById('user-edit').classList.toggle('no-active')
|
document.getElementById('user-edit').classList.toggle('no-active')
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue