mirror of
https://github.com/Troplo/Colubrina.git
synced 2024-11-25 12:46:42 +11:00
update
This commit is contained in:
parent
f17a9d3027
commit
98218285ef
19 changed files with 226 additions and 425 deletions
|
@ -277,7 +277,8 @@ async function init() {
|
||||||
username: "Colubrina",
|
username: "Colubrina",
|
||||||
id: 0,
|
id: 0,
|
||||||
bot: true,
|
bot: true,
|
||||||
email: "colubrina@troplo.com"
|
email: "colubrina@troplo.com",
|
||||||
|
banned: true
|
||||||
})
|
})
|
||||||
await User.update(
|
await User.update(
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,7 @@ app.use(bodyParser.urlencoded({ extended: true }))
|
||||||
app.use("/api/v1/user", require("./routes/user.js"))
|
app.use("/api/v1/user", require("./routes/user.js"))
|
||||||
app.use("/api/v1/themes", require("./routes/theme.js"))
|
app.use("/api/v1/themes", require("./routes/theme.js"))
|
||||||
app.use("/api/v1/communications", require("./routes/communications.js"))
|
app.use("/api/v1/communications", require("./routes/communications.js"))
|
||||||
|
app.use("/api/v1/friends", require("./routes/friends.js"))
|
||||||
app.use("/api/v1/admin", require("./routes/admin.js"))
|
app.use("/api/v1/admin", require("./routes/admin.js"))
|
||||||
app.use("/usercontent", require("./routes/usercontent.js"))
|
app.use("/usercontent", require("./routes/usercontent.js"))
|
||||||
app.use("/api/v1/usercontent", require("./routes/usercontent.js"))
|
app.use("/api/v1/usercontent", require("./routes/usercontent.js"))
|
||||||
|
|
|
@ -19,6 +19,10 @@ module.exports = async function (req, res, next) {
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
if (user) {
|
if (user) {
|
||||||
|
if (user.banned) {
|
||||||
|
res.status(401).json(Errors.banned)
|
||||||
|
return
|
||||||
|
}
|
||||||
await user.update({
|
await user.update({
|
||||||
lastSeenAt: new Date().toISOString()
|
lastSeenAt: new Date().toISOString()
|
||||||
})
|
})
|
||||||
|
|
|
@ -30,18 +30,22 @@ module.exports = async function (socket, next) {
|
||||||
raw: true
|
raw: true
|
||||||
})
|
})
|
||||||
if (user) {
|
if (user) {
|
||||||
socket.user = user
|
if (user.banned) {
|
||||||
next()
|
socket.user = {
|
||||||
|
id: null,
|
||||||
|
username: "Not Authenticated"
|
||||||
|
}
|
||||||
|
next()
|
||||||
|
} else {
|
||||||
|
socket.user = user
|
||||||
|
next()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
socket.user = {
|
socket.user = {
|
||||||
id: null,
|
id: null,
|
||||||
username: "Not Authenticated"
|
username: "Not Authenticated"
|
||||||
}
|
}
|
||||||
socket.compassUser = {
|
|
||||||
id: null,
|
|
||||||
username: "BC-NOAUTH"
|
|
||||||
}
|
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -49,10 +53,6 @@ module.exports = async function (socket, next) {
|
||||||
id: null,
|
id: null,
|
||||||
username: "Not Authenticated"
|
username: "Not Authenticated"
|
||||||
}
|
}
|
||||||
socket.compassUser = {
|
|
||||||
id: null,
|
|
||||||
username: "BC-NOAUTH"
|
|
||||||
}
|
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -60,10 +60,6 @@ module.exports = async function (socket, next) {
|
||||||
id: null,
|
id: null,
|
||||||
username: "Not Authenticated"
|
username: "Not Authenticated"
|
||||||
}
|
}
|
||||||
socket.compassUser = {
|
|
||||||
id: null,
|
|
||||||
username: "BC-NOAUTH"
|
|
||||||
}
|
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,8 @@ let Errors = {
|
||||||
registrationsDisabled: [
|
registrationsDisabled: [
|
||||||
"Registrations are currently disabled on this instance. Please try again later.",
|
"Registrations are currently disabled on this instance. Please try again later.",
|
||||||
400
|
400
|
||||||
]
|
],
|
||||||
|
banned: ["You are banned from this instance.", 400]
|
||||||
}
|
}
|
||||||
|
|
||||||
function processErrors(errorName) {
|
function processErrors(errorName) {
|
||||||
|
|
|
@ -11,17 +11,11 @@ module.exports = {
|
||||||
session: {
|
session: {
|
||||||
type: Sequelize.STRING
|
type: Sequelize.STRING
|
||||||
},
|
},
|
||||||
compassUserId: {
|
|
||||||
type: Sequelize.BIGINT
|
|
||||||
},
|
|
||||||
sussiId: {
|
|
||||||
type: Sequelize.STRING
|
|
||||||
},
|
|
||||||
other: {
|
other: {
|
||||||
type: Sequelize.JSON
|
type: Sequelize.JSON
|
||||||
},
|
},
|
||||||
instance: {
|
expiredAt: {
|
||||||
type: Sequelize.STRING
|
type: Sequelize.DATE
|
||||||
},
|
},
|
||||||
createdAt: {
|
createdAt: {
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
"use strict"
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
up: async (queryInterface, Sequelize) => {
|
|
||||||
await queryInterface.addColumn("Sessions", "expiredAt", {
|
|
||||||
type: Sequelize.DATE
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
down: async (queryInterface, Sequelize) => {
|
|
||||||
/**
|
|
||||||
* Add reverting commands here.
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
* await queryInterface.dropTable('users');
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
20
backend/migrations/20220729091059-isBanned.js
Normal file
20
backend/migrations/20220729091059-isBanned.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
"use strict"
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
async up(queryInterface, Sequelize) {
|
||||||
|
await queryInterface.addColumn("Users", "banned", {
|
||||||
|
type: Sequelize.BOOLEAN,
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
async down(queryInterface, Sequelize) {
|
||||||
|
/**
|
||||||
|
* Add reverting commands here.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* await queryInterface.dropTable('users');
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,10 +14,7 @@ module.exports = (sequelize, DataTypes) => {
|
||||||
Session.init(
|
Session.init(
|
||||||
{
|
{
|
||||||
session: DataTypes.STRING,
|
session: DataTypes.STRING,
|
||||||
compassUserId: DataTypes.BIGINT,
|
|
||||||
sussiId: DataTypes.STRING,
|
|
||||||
other: DataTypes.JSON,
|
other: DataTypes.JSON,
|
||||||
instance: DataTypes.STRING,
|
|
||||||
userId: DataTypes.BIGINT,
|
userId: DataTypes.BIGINT,
|
||||||
expiredAt: DataTypes.DATE
|
expiredAt: DataTypes.DATE
|
||||||
},
|
},
|
||||||
|
|
|
@ -153,6 +153,11 @@ module.exports = (sequelize, DataTypes) => {
|
||||||
lastSeenAt: {
|
lastSeenAt: {
|
||||||
type: DataTypes.DATE,
|
type: DataTypes.DATE,
|
||||||
allowNull: true
|
allowNull: true
|
||||||
|
},
|
||||||
|
banned: {
|
||||||
|
type: DataTypes.BOOLEAN,
|
||||||
|
allowNull: false,
|
||||||
|
defaultValue: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -58,7 +58,7 @@ router.get("/metrics", auth, async (req, res, next) => {
|
||||||
createdAt: createdAt
|
createdAt: createdAt
|
||||||
},
|
},
|
||||||
attributes: {
|
attributes: {
|
||||||
exclude: ["totp", "compassSession", "password"]
|
exclude: ["totp", "password"]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const messages = await Message.findAll({
|
const messages = await Message.findAll({
|
||||||
|
@ -66,7 +66,7 @@ router.get("/metrics", auth, async (req, res, next) => {
|
||||||
createdAt: createdAt
|
createdAt: createdAt
|
||||||
},
|
},
|
||||||
attributes: {
|
attributes: {
|
||||||
exclude: ["totp", "compassSession", "password"]
|
exclude: ["totp", "password"]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ router.get("/users", auth, async (req, res, next) => {
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
attributes: {
|
attributes: {
|
||||||
exclude: ["totp", "compassSession", "password"]
|
exclude: ["totp", "password"]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
res.json(users)
|
res.json(users)
|
||||||
|
@ -154,7 +154,7 @@ router.get("/themes", auth, async (req, res, next) => {
|
||||||
model: User,
|
model: User,
|
||||||
as: "user",
|
as: "user",
|
||||||
attributes: {
|
attributes: {
|
||||||
exclude: ["totp", "compassSession", "password"]
|
exclude: ["totp", "password"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,6 +47,7 @@ const upload = multer({
|
||||||
|
|
||||||
const resolveEmbeds = require("../lib/resolveEmbeds.js")
|
const resolveEmbeds = require("../lib/resolveEmbeds.js")
|
||||||
const paginate = require("jw-paginate")
|
const paginate = require("jw-paginate")
|
||||||
|
|
||||||
async function createMessage(req, type, content, association, userId) {
|
async function createMessage(req, type, content, association, userId) {
|
||||||
const io = req.app.get("io")
|
const io = req.app.get("io")
|
||||||
const message = await Message.create({
|
const message = await Message.create({
|
||||||
|
@ -133,6 +134,7 @@ async function createMessage(req, type, content, association, userId) {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
router.get("/", auth, async (req, res, next) => {
|
router.get("/", auth, async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
let chats = await ChatAssociation.findAll({
|
let chats = await ChatAssociation.findAll({
|
||||||
|
@ -748,31 +750,6 @@ router.post("/association/:id", auth, async (req, res, next) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
router.get("/friends", auth, async (req, res, next) => {
|
|
||||||
try {
|
|
||||||
let friends = await Friend.findAll({
|
|
||||||
where: {
|
|
||||||
userId: req.user.id
|
|
||||||
},
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
model: User,
|
|
||||||
as: "user",
|
|
||||||
attributes: ["id", "username", "avatar", "createdAt", "updatedAt"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
model: User,
|
|
||||||
as: "user2",
|
|
||||||
attributes: ["id", "username", "avatar", "createdAt", "updatedAt"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
res.json(friends)
|
|
||||||
} catch (err) {
|
|
||||||
next(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
router.get("/users", auth, async (req, res, next) => {
|
router.get("/users", auth, async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
const users = await User.findAll({
|
const users = await User.findAll({
|
||||||
|
@ -780,11 +757,9 @@ router.get("/users", auth, async (req, res, next) => {
|
||||||
"id",
|
"id",
|
||||||
"username",
|
"username",
|
||||||
"name",
|
"name",
|
||||||
|
|
||||||
"avatar",
|
"avatar",
|
||||||
"createdAt",
|
"createdAt",
|
||||||
"updatedAt",
|
"updatedAt",
|
||||||
|
|
||||||
"status",
|
"status",
|
||||||
"admin"
|
"admin"
|
||||||
]
|
]
|
||||||
|
@ -795,141 +770,6 @@ router.get("/users", auth, async (req, res, next) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
router.post("/friends", auth, async (req, res, next) => {
|
|
||||||
try {
|
|
||||||
const io = req.app.get("io")
|
|
||||||
let friendRes
|
|
||||||
try {
|
|
||||||
friendRes = req.body.friend.split(":")
|
|
||||||
} catch {
|
|
||||||
friendRes = req.body.friend
|
|
||||||
}
|
|
||||||
const user = await User.findOne({
|
|
||||||
where: {
|
|
||||||
username: friendRes[0] || friendRes
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (user) {
|
|
||||||
const friend = await Friend.findOne({
|
|
||||||
where: {
|
|
||||||
userId: req.user.id,
|
|
||||||
friendId: user.id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (friend) {
|
|
||||||
throw Errors.friendAlreadyFriends
|
|
||||||
} else {
|
|
||||||
if (!user.privacy.communications.enabled) {
|
|
||||||
throw Errors.communicationsUserNotOptedIn
|
|
||||||
} else {
|
|
||||||
const newFriend = await Friend.create({
|
|
||||||
userId: req.user.id,
|
|
||||||
friendId: user.id
|
|
||||||
})
|
|
||||||
const remoteFriend = await Friend.create({
|
|
||||||
userId: user.id,
|
|
||||||
friendId: req.user.id,
|
|
||||||
status: "pendingCanAccept"
|
|
||||||
})
|
|
||||||
io.to(user.id).emit("friendUpdate", {})
|
|
||||||
io.to(req.user.id).emit("friendUpdate", {})
|
|
||||||
io.to(user.id).emit("friendRequest", {
|
|
||||||
...remoteFriend.dataValues,
|
|
||||||
user: {
|
|
||||||
username: req.user.username,
|
|
||||||
discussionsImage: req.user.discussionsImage,
|
|
||||||
avatar: req.user.avatar,
|
|
||||||
id: req.user.id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
res.json(newFriend)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw Errors.communicationsUserNotFound
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
next(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
router.delete("/friends/:id", auth, async (req, res, next) => {
|
|
||||||
try {
|
|
||||||
const io = req.app.get("io")
|
|
||||||
const friend = await Friend.findOne({
|
|
||||||
where: {
|
|
||||||
userId: req.user.id,
|
|
||||||
id: req.params.id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (friend) {
|
|
||||||
await friend.destroy()
|
|
||||||
await Friend.destroy({
|
|
||||||
where: {
|
|
||||||
userId: friend.friendId,
|
|
||||||
friendId: req.user.id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
io.to(friend.friendId).emit("friendUpdate", {})
|
|
||||||
io.to(req.user.id).emit("friendUpdate", {})
|
|
||||||
res.sendStatus(204)
|
|
||||||
} else {
|
|
||||||
throw Errors.friendNotFound
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
next(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
router.put("/friends/:id", auth, async (req, res, next) => {
|
|
||||||
try {
|
|
||||||
const io = req.app.get("io")
|
|
||||||
const friend = await Friend.findOne({
|
|
||||||
where: {
|
|
||||||
id: req.params.id,
|
|
||||||
userId: req.user.id,
|
|
||||||
status: "pendingCanAccept"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (friend) {
|
|
||||||
await friend.update({
|
|
||||||
status: "accepted"
|
|
||||||
})
|
|
||||||
const remoteFriend = await Friend.findOne({
|
|
||||||
where: {
|
|
||||||
userId: friend.friendId,
|
|
||||||
friendId: friend.userId
|
|
||||||
},
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
model: User,
|
|
||||||
as: "user",
|
|
||||||
attributes: ["id", "username", "createdAt", "updatedAt"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
model: User,
|
|
||||||
as: "user2",
|
|
||||||
attributes: ["id", "username", "createdAt", "updatedAt"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
await remoteFriend.update({
|
|
||||||
status: "accepted"
|
|
||||||
})
|
|
||||||
io.to(friend.userId).emit("friendUpdate", {})
|
|
||||||
io.to(remoteFriend.userId).emit("friendUpdate", {})
|
|
||||||
io.to(remoteFriend.userId).emit("friendAccepted", {
|
|
||||||
...remoteFriend.dataValues
|
|
||||||
})
|
|
||||||
res.json(friend)
|
|
||||||
} else {
|
|
||||||
throw Errors.friendNotFound
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
next(err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
router.get("/search", auth, async (req, res, next) => {
|
router.get("/search", auth, async (req, res, next) => {
|
||||||
try {
|
try {
|
||||||
const friends = await Friend.findAll({
|
const friends = await Friend.findAll({
|
||||||
|
@ -988,7 +828,6 @@ router.get("/:id", auth, async (req, res, next) => {
|
||||||
attributes: [
|
attributes: [
|
||||||
"username",
|
"username",
|
||||||
"name",
|
"name",
|
||||||
|
|
||||||
"avatar",
|
"avatar",
|
||||||
"id",
|
"id",
|
||||||
"createdAt",
|
"createdAt",
|
||||||
|
@ -1230,7 +1069,6 @@ router.get("/:id/search", auth, async (req, res, next) => {
|
||||||
attributes: [
|
attributes: [
|
||||||
"username",
|
"username",
|
||||||
"name",
|
"name",
|
||||||
|
|
||||||
"avatar",
|
"avatar",
|
||||||
"id",
|
"id",
|
||||||
"createdAt",
|
"createdAt",
|
||||||
|
@ -1247,7 +1085,6 @@ router.get("/:id/search", auth, async (req, res, next) => {
|
||||||
attributes: [
|
attributes: [
|
||||||
"username",
|
"username",
|
||||||
"name",
|
"name",
|
||||||
|
|
||||||
"avatar",
|
"avatar",
|
||||||
"id",
|
"id",
|
||||||
"createdAt",
|
"createdAt",
|
||||||
|
@ -1309,7 +1146,6 @@ router.delete("/association/:id", auth, async (req, res, next) => {
|
||||||
attributes: [
|
attributes: [
|
||||||
"username",
|
"username",
|
||||||
"name",
|
"name",
|
||||||
|
|
||||||
"avatar",
|
"avatar",
|
||||||
"id",
|
"id",
|
||||||
"createdAt",
|
"createdAt",
|
||||||
|
@ -1337,7 +1173,6 @@ router.delete("/association/:id", auth, async (req, res, next) => {
|
||||||
attributes: [
|
attributes: [
|
||||||
"username",
|
"username",
|
||||||
"name",
|
"name",
|
||||||
|
|
||||||
"avatar",
|
"avatar",
|
||||||
"id",
|
"id",
|
||||||
"createdAt",
|
"createdAt",
|
||||||
|
@ -1356,7 +1191,6 @@ router.delete("/association/:id", auth, async (req, res, next) => {
|
||||||
attributes: [
|
attributes: [
|
||||||
"username",
|
"username",
|
||||||
"name",
|
"name",
|
||||||
|
|
||||||
"avatar",
|
"avatar",
|
||||||
"id",
|
"id",
|
||||||
"createdAt",
|
"createdAt",
|
||||||
|
@ -1371,7 +1205,6 @@ router.delete("/association/:id", auth, async (req, res, next) => {
|
||||||
attributes: [
|
attributes: [
|
||||||
"username",
|
"username",
|
||||||
"name",
|
"name",
|
||||||
|
|
||||||
"avatar",
|
"avatar",
|
||||||
"id",
|
"id",
|
||||||
"createdAt",
|
"createdAt",
|
||||||
|
|
167
backend/routes/friends.js
Normal file
167
backend/routes/friends.js
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
const auth = require("../lib/authorize")
|
||||||
|
const { Friend, User } = require("../models")
|
||||||
|
const Errors = require("../lib/errors")
|
||||||
|
const express = require("express")
|
||||||
|
const router = express.Router()
|
||||||
|
|
||||||
|
router.get("/", auth, async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
let friends = await Friend.findAll({
|
||||||
|
where: {
|
||||||
|
userId: req.user.id
|
||||||
|
},
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: User,
|
||||||
|
as: "user",
|
||||||
|
attributes: ["id", "username", "avatar", "createdAt", "updatedAt"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: User,
|
||||||
|
as: "user2",
|
||||||
|
attributes: ["id", "username", "avatar", "createdAt", "updatedAt"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
res.json(friends)
|
||||||
|
} catch (err) {
|
||||||
|
next(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.post("/", auth, async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const io = req.app.get("io")
|
||||||
|
let friendRes
|
||||||
|
try {
|
||||||
|
friendRes = req.body.friend.split(":")
|
||||||
|
} catch {
|
||||||
|
friendRes = req.body.friend
|
||||||
|
}
|
||||||
|
const user = await User.findOne({
|
||||||
|
where: {
|
||||||
|
username: friendRes[0] || friendRes
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (user) {
|
||||||
|
const friend = await Friend.findOne({
|
||||||
|
where: {
|
||||||
|
userId: req.user.id,
|
||||||
|
friendId: user.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (friend) {
|
||||||
|
throw Errors.friendAlreadyFriends
|
||||||
|
} else {
|
||||||
|
if (!user.privacy.communications.enabled) {
|
||||||
|
throw Errors.communicationsUserNotOptedIn
|
||||||
|
} else {
|
||||||
|
const newFriend = await Friend.create({
|
||||||
|
userId: req.user.id,
|
||||||
|
friendId: user.id
|
||||||
|
})
|
||||||
|
const remoteFriend = await Friend.create({
|
||||||
|
userId: user.id,
|
||||||
|
friendId: req.user.id,
|
||||||
|
status: "pendingCanAccept"
|
||||||
|
})
|
||||||
|
io.to(user.id).emit("friendUpdate", {})
|
||||||
|
io.to(req.user.id).emit("friendUpdate", {})
|
||||||
|
io.to(user.id).emit("friendRequest", {
|
||||||
|
...remoteFriend.dataValues,
|
||||||
|
user: {
|
||||||
|
username: req.user.username,
|
||||||
|
discussionsImage: req.user.discussionsImage,
|
||||||
|
avatar: req.user.avatar,
|
||||||
|
id: req.user.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
res.json(newFriend)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw Errors.communicationsUserNotFound
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
next(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.delete("/:id", auth, async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const io = req.app.get("io")
|
||||||
|
const friend = await Friend.findOne({
|
||||||
|
where: {
|
||||||
|
userId: req.user.id,
|
||||||
|
id: req.params.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (friend) {
|
||||||
|
await friend.destroy()
|
||||||
|
await Friend.destroy({
|
||||||
|
where: {
|
||||||
|
userId: friend.friendId,
|
||||||
|
friendId: req.user.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
io.to(friend.friendId).emit("friendUpdate", {})
|
||||||
|
io.to(req.user.id).emit("friendUpdate", {})
|
||||||
|
res.sendStatus(204)
|
||||||
|
} else {
|
||||||
|
throw Errors.friendNotFound
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
next(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
router.put("/:id", auth, async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const io = req.app.get("io")
|
||||||
|
const friend = await Friend.findOne({
|
||||||
|
where: {
|
||||||
|
id: req.params.id,
|
||||||
|
userId: req.user.id,
|
||||||
|
status: "pendingCanAccept"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (friend) {
|
||||||
|
await friend.update({
|
||||||
|
status: "accepted"
|
||||||
|
})
|
||||||
|
const remoteFriend = await Friend.findOne({
|
||||||
|
where: {
|
||||||
|
userId: friend.friendId,
|
||||||
|
friendId: friend.userId
|
||||||
|
},
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
model: User,
|
||||||
|
as: "user",
|
||||||
|
attributes: ["id", "username", "createdAt", "updatedAt"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
model: User,
|
||||||
|
as: "user2",
|
||||||
|
attributes: ["id", "username", "createdAt", "updatedAt"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
await remoteFriend.update({
|
||||||
|
status: "accepted"
|
||||||
|
})
|
||||||
|
io.to(friend.userId).emit("friendUpdate", {})
|
||||||
|
io.to(remoteFriend.userId).emit("friendUpdate", {})
|
||||||
|
io.to(remoteFriend.userId).emit("friendAccepted", {
|
||||||
|
...remoteFriend.dataValues
|
||||||
|
})
|
||||||
|
res.json(friend)
|
||||||
|
} else {
|
||||||
|
throw Errors.friendNotFound
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
next(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
module.exports = router
|
|
@ -68,12 +68,8 @@ router.post("/login", async (req, res, next) => {
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
const session = await Session.create({
|
const session = await Session.create({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
instance: req.body.instance || "",
|
|
||||||
session: "COLUBRINA-" + cryptoRandomString({ length: 128 }),
|
session: "COLUBRINA-" + cryptoRandomString({ length: 128 }),
|
||||||
compassUserId: user.compassUserId,
|
|
||||||
sussiId: user.sussiId,
|
|
||||||
expiredAt: new Date(new Date().getTime() + 1000 * 60 * 60 * 24 * 30),
|
expiredAt: new Date(new Date().getTime() + 1000 * 60 * 60 * 24 * 30),
|
||||||
compassSession: user.compassSession,
|
|
||||||
other: {
|
other: {
|
||||||
ip: req.header("x-real-ip") || req.ip,
|
ip: req.header("x-real-ip") || req.ip,
|
||||||
location: ip.country
|
location: ip.country
|
||||||
|
@ -113,6 +109,7 @@ router.post("/login", async (req, res, next) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (user) {
|
if (user) {
|
||||||
|
if (user.banned) throw Errors.banned
|
||||||
if (await checkPassword(req.body.password, user.password)) {
|
if (await checkPassword(req.body.password, user.password)) {
|
||||||
if (user.totpEnabled) {
|
if (user.totpEnabled) {
|
||||||
const verified = speakeasy.totp.verify({
|
const verified = speakeasy.totp.verify({
|
||||||
|
@ -160,12 +157,8 @@ router.post("/register", async (req, res, next) => {
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
const session = await Session.create({
|
const session = await Session.create({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
instance: req.body.instance || "",
|
|
||||||
session: "COLUBRINA-" + cryptoRandomString({ length: 128 }),
|
session: "COLUBRINA-" + cryptoRandomString({ length: 128 }),
|
||||||
compassUserId: user.compassUserId,
|
|
||||||
sussiId: user.sussiId,
|
|
||||||
expiredAt: new Date(new Date().getTime() + 1000 * 60 * 60 * 24 * 30),
|
expiredAt: new Date(new Date().getTime() + 1000 * 60 * 60 * 24 * 30),
|
||||||
compassSession: user.compassSession,
|
|
||||||
other: {
|
other: {
|
||||||
ip: req.header("x-real-ip") || req.ip,
|
ip: req.header("x-real-ip") || req.ip,
|
||||||
location: ip.country
|
location: ip.country
|
||||||
|
|
126
src/main.js
126
src/main.js
|
@ -9,10 +9,8 @@ import Toast from "vue-toastification"
|
||||||
import "./assets/styles.css"
|
import "./assets/styles.css"
|
||||||
import "vue-toastification/dist/index.css"
|
import "vue-toastification/dist/index.css"
|
||||||
import "./registerServiceWorker"
|
import "./registerServiceWorker"
|
||||||
import VueSanitize from "vue-sanitize"
|
|
||||||
import "@mdi/font/css/materialdesignicons.css"
|
import "@mdi/font/css/materialdesignicons.css"
|
||||||
import "./plugins/dayjs"
|
import "./plugins/dayjs"
|
||||||
import VueApollo from "./plugins/apollo"
|
|
||||||
import SocketIO from "socket.io-client"
|
import SocketIO from "socket.io-client"
|
||||||
import twemoji from "twemoji"
|
import twemoji from "twemoji"
|
||||||
import VueNativeNotification from "vue-native-notification"
|
import VueNativeNotification from "vue-native-notification"
|
||||||
|
@ -84,129 +82,6 @@ Vue.use({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
Vue.use(VueSanitize, {
|
|
||||||
allowedTags: [
|
|
||||||
"address",
|
|
||||||
"article",
|
|
||||||
"aside",
|
|
||||||
"footer",
|
|
||||||
"header",
|
|
||||||
"h1",
|
|
||||||
"h2",
|
|
||||||
"h3",
|
|
||||||
"h4",
|
|
||||||
"h5",
|
|
||||||
"h6",
|
|
||||||
"hgroup",
|
|
||||||
"main",
|
|
||||||
"nav",
|
|
||||||
"section",
|
|
||||||
"blockquote",
|
|
||||||
"dd",
|
|
||||||
"div",
|
|
||||||
"dl",
|
|
||||||
"dt",
|
|
||||||
"figcaption",
|
|
||||||
"figure",
|
|
||||||
"hr",
|
|
||||||
"li",
|
|
||||||
"main",
|
|
||||||
"ol",
|
|
||||||
"p",
|
|
||||||
"pre",
|
|
||||||
"ul",
|
|
||||||
"a",
|
|
||||||
"abbr",
|
|
||||||
"b",
|
|
||||||
"bdi",
|
|
||||||
"bdo",
|
|
||||||
"br",
|
|
||||||
"cite",
|
|
||||||
"code",
|
|
||||||
"data",
|
|
||||||
"dfn",
|
|
||||||
"em",
|
|
||||||
"i",
|
|
||||||
"kbd",
|
|
||||||
"mark",
|
|
||||||
"q",
|
|
||||||
"rb",
|
|
||||||
"rp",
|
|
||||||
"rt",
|
|
||||||
"rtc",
|
|
||||||
"ruby",
|
|
||||||
"s",
|
|
||||||
"samp",
|
|
||||||
"small",
|
|
||||||
"span",
|
|
||||||
"strong",
|
|
||||||
"sub",
|
|
||||||
"sup",
|
|
||||||
"time",
|
|
||||||
"u",
|
|
||||||
"var",
|
|
||||||
"wbr",
|
|
||||||
"caption",
|
|
||||||
"col",
|
|
||||||
"colgroup",
|
|
||||||
"table",
|
|
||||||
"tbody",
|
|
||||||
"td",
|
|
||||||
"tfoot",
|
|
||||||
"th",
|
|
||||||
"thead",
|
|
||||||
"tr",
|
|
||||||
"img"
|
|
||||||
],
|
|
||||||
disallowedTagsMode: "discard",
|
|
||||||
allowedAttributes: {
|
|
||||||
a: ["href", "name", "target"],
|
|
||||||
img: [
|
|
||||||
"src",
|
|
||||||
"srcset",
|
|
||||||
"alt",
|
|
||||||
"title",
|
|
||||||
"width",
|
|
||||||
"height",
|
|
||||||
"loading",
|
|
||||||
"style"
|
|
||||||
],
|
|
||||||
tr: ["style"],
|
|
||||||
td: ["style"],
|
|
||||||
table: ["style", "border", "cellpadding", "cellspacing"]
|
|
||||||
},
|
|
||||||
allowedStyles: {
|
|
||||||
"*": {
|
|
||||||
// Match HEX and RGB
|
|
||||||
"text-align": [/^left$/, /^right$/, /^center$/],
|
|
||||||
// Match any number with px, em, or %
|
|
||||||
"font-size": [/^\d+(?:px|em|%)$/],
|
|
||||||
"font-weight": [/^\d+$/],
|
|
||||||
"font-style": [/^\d+$/],
|
|
||||||
height: [/^\d+(?:px|em|%)$/],
|
|
||||||
width: [/^\d+(?:px|em|%)$/]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// Lots of these won't come up by default because we don't allow them
|
|
||||||
selfClosing: [
|
|
||||||
"img",
|
|
||||||
"br",
|
|
||||||
"hr",
|
|
||||||
"area",
|
|
||||||
"base",
|
|
||||||
"basefont",
|
|
||||||
"input",
|
|
||||||
"link",
|
|
||||||
"meta"
|
|
||||||
],
|
|
||||||
// URL schemes we permit
|
|
||||||
allowedSchemes: ["http", "https", "ftp", "mailto", "tel"],
|
|
||||||
|
|
||||||
allowedSchemesByTag: {},
|
|
||||||
allowedSchemesAppliedToAttributes: ["href", "src", "cite"],
|
|
||||||
allowProtocolRelative: true,
|
|
||||||
enforceHtmlBoundary: false
|
|
||||||
})
|
|
||||||
Vue.use(require("vue-shortkey"))
|
Vue.use(require("vue-shortkey"))
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
Vue.use(VueAxios, axios)
|
Vue.use(VueAxios, axios)
|
||||||
|
@ -220,6 +95,5 @@ new Vue({
|
||||||
router,
|
router,
|
||||||
store,
|
store,
|
||||||
vuetify,
|
vuetify,
|
||||||
VueApollo,
|
|
||||||
render: (h) => h(App)
|
render: (h) => h(App)
|
||||||
}).$mount("#app")
|
}).$mount("#app")
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
import ApolloClient, { InMemoryCache } from "apollo-boost"
|
|
||||||
import Vue from "vue"
|
|
||||||
|
|
||||||
const cache = new InMemoryCache()
|
|
||||||
|
|
||||||
const apolloClient = new ApolloClient({
|
|
||||||
uri: "/graphql",
|
|
||||||
headers: {
|
|
||||||
CompassAPIKey: localStorage.getItem("apiKey"),
|
|
||||||
compassInstance: localStorage.getItem("schoolInstance")
|
|
||||||
},
|
|
||||||
cache
|
|
||||||
})
|
|
||||||
|
|
||||||
Object.defineProperties(Vue.prototype, {
|
|
||||||
$apollo: {
|
|
||||||
get() {
|
|
||||||
return apolloClient
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
export default apolloClient
|
|
|
@ -44,7 +44,7 @@ export default {
|
||||||
value: "name"
|
value: "name"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Compass User ID",
|
text: "User ID",
|
||||||
value: "user.id"
|
value: "user.id"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -300,29 +300,6 @@
|
||||||
</p>
|
</p>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
<v-row
|
|
||||||
v-else-if="embed.type === 'compass'"
|
|
||||||
@click="$router.push(embed.path)"
|
|
||||||
style="cursor: pointer"
|
|
||||||
>
|
|
||||||
<v-container
|
|
||||||
:style="
|
|
||||||
'background: url(/' +
|
|
||||||
embed.compass.banner +
|
|
||||||
')'
|
|
||||||
"
|
|
||||||
style="color: white"
|
|
||||||
class="rounded"
|
|
||||||
>
|
|
||||||
<h4>BetterCompass</h4>
|
|
||||||
<h3>
|
|
||||||
{{ embed.compass.name }}
|
|
||||||
</h3>
|
|
||||||
<p>
|
|
||||||
{{ embed.compass.displayName }}
|
|
||||||
</p>
|
|
||||||
</v-container>
|
|
||||||
</v-row>
|
|
||||||
<template v-else-if="embed.type === 'image'">
|
<template v-else-if="embed.type === 'image'">
|
||||||
<v-hover v-slot="{ hover }">
|
<v-hover v-slot="{ hover }">
|
||||||
<div>
|
<div>
|
||||||
|
@ -1108,27 +1085,6 @@
|
||||||
</p>
|
</p>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
<v-row
|
|
||||||
v-if="embed.type === 'compass'"
|
|
||||||
@click="$router.push(embed.path)"
|
|
||||||
style="cursor: pointer"
|
|
||||||
>
|
|
||||||
<v-container
|
|
||||||
:style="
|
|
||||||
'background: url(/' +
|
|
||||||
embed.compass.banner +
|
|
||||||
')'
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<h4>BetterCompass</h4>
|
|
||||||
<h3>
|
|
||||||
{{ embed.compass.name }}
|
|
||||||
</h3>
|
|
||||||
<p>
|
|
||||||
{{ embed.compass.displayName }}
|
|
||||||
</p>
|
|
||||||
</v-container>
|
|
||||||
</v-row>
|
|
||||||
<template v-else-if="embed.type === 'image'">
|
<template v-else-if="embed.type === 'image'">
|
||||||
<v-hover v-slot="{ hover }">
|
<v-hover v-slot="{ hover }">
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -281,7 +281,7 @@ export default {
|
||||||
},
|
},
|
||||||
acceptFriend(friend) {
|
acceptFriend(friend) {
|
||||||
this.axios
|
this.axios
|
||||||
.put("/api/v1/communications/friends/" + friend.id, {
|
.put("/api/v1/friends/" + friend.id, {
|
||||||
friend: friend.id,
|
friend: friend.id,
|
||||||
status: "accepted"
|
status: "accepted"
|
||||||
})
|
})
|
||||||
|
@ -294,7 +294,7 @@ export default {
|
||||||
},
|
},
|
||||||
removeFriend(friend) {
|
removeFriend(friend) {
|
||||||
this.axios
|
this.axios
|
||||||
.delete("/api/v1/communications/friends/" + friend.id)
|
.delete("/api/v1/friends/" + friend.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.getFriends()
|
this.getFriends()
|
||||||
})
|
})
|
||||||
|
@ -305,7 +305,7 @@ export default {
|
||||||
addFriend(user) {
|
addFriend(user) {
|
||||||
if (user) {
|
if (user) {
|
||||||
this.axios
|
this.axios
|
||||||
.post("/api/v1/communications/friends", {
|
.post("/api/v1/friends", {
|
||||||
friend: user.username + ":" + user.instance
|
friend: user.username + ":" + user.instance
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -317,7 +317,7 @@ export default {
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.axios
|
this.axios
|
||||||
.post("/api/v1/communications/friends", {
|
.post("/api/v1/friends", {
|
||||||
friend: this.friend
|
friend: this.friend
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -330,7 +330,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getFriends() {
|
getFriends() {
|
||||||
this.axios.get("/api/v1/communications/friends").then((res) => {
|
this.axios.get("/api/v1/friends").then((res) => {
|
||||||
this.friends = res.data
|
this.friends = res.data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue