Resolved merge conflict on new changes

This commit is contained in:
Andreas 2023-07-26 19:36:51 +02:00
commit 6b42a39bae
13 changed files with 455 additions and 103 deletions

15
package-lock.json generated
View File

@ -9,6 +9,7 @@
"version": "0.1.0",
"dependencies": {
"@types/bcrypt": "^5.0.0",
"@types/cookie": "^0.5.1",
"@types/node": "20.1.7",
"@types/react": "18.2.6",
"@types/react-bootstrap": "^0.32.32",
@ -16,6 +17,7 @@
"autoprefixer": "10.4.14",
"bcrypt": "^5.1.0",
"bootstrap": "^5.3.0",
"cookie": "^0.5.0",
"eslint": "8.40.0",
"eslint-config-next": "13.4.2",
"mysql": "^2.18.1",
@ -529,6 +531,11 @@
"@types/node": "*"
}
},
"node_modules/@types/cookie": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.5.1.tgz",
"integrity": "sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g=="
},
"node_modules/@types/debug": {
"version": "4.1.8",
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz",
@ -1359,6 +1366,14 @@
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
"integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ=="
},
"node_modules/cookie": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz",
"integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",

View File

@ -10,6 +10,7 @@
},
"dependencies": {
"@types/bcrypt": "^5.0.0",
"@types/cookie": "^0.5.1",
"@types/node": "20.1.7",
"@types/react": "18.2.6",
"@types/react-bootstrap": "^0.32.32",
@ -17,6 +18,7 @@
"autoprefixer": "10.4.14",
"bcrypt": "^5.1.0",
"bootstrap": "^5.3.0",
"cookie": "^0.5.0",
"eslint": "8.40.0",
"eslint-config-next": "13.4.2",
"mysql": "^2.18.1",

View File

@ -14,7 +14,9 @@ type Post = {
title: String,
content: String
}
async function getData(slug:String):Promise<Array<any>> {
// Get all posts from the API
const res = await fetch(`http://localhost:3000/api/post/${slug}`);
// The return value is *not* serialized
// You can return Date, Map, Set, etc.

29
src/app/projects/page.tsx Normal file
View File

@ -0,0 +1,29 @@
import Header from "@/components/header";
import PageContainer from "@/components/page-container";
import Navbar from "@/components/navbar";
import Sidebar from "@/components/sidebar";
import ArticlePreview from "@/components/news/article-preview"
import ReactDOM from "react";
import "public/global.css"
import "@/app/index.css"
export default function Page() {
return <div className={`root`}>
<Header/>
<Navbar/>
<PageContainer>
<Sidebar>
<h1>
Filters
</h1>
<ul><li>filter 1</li><li>filter 2</li><li>filter 3</li></ul>
</Sidebar>
<main>
<ArticlePreview/>
<ArticlePreview/>
<ArticlePreview/>
</main>
</PageContainer>
</div>;
}

View File

@ -0,0 +1,41 @@
import { Sequelize, DataTypes, Optional, Model, UUIDV4 } from 'sequelize';
import { MPost } from '@/model/sequelize/Post';
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'db.sqlite'
});
interface AttachmentAttributes{
id: string;
path: string;
post_id: number;
};
interface AttachmentCreationAttributes extends Optional<AttachmentAttributes, 'id'>{};
class AttachmentModel extends Model<AttachmentAttributes, AttachmentCreationAttributes>{
id:string = "";
path:string = "";
post_id:number|undefined;
createdAt?: Date;
updatedAt?: Date;
// declare title
}
export const MAttachment = sequelize.define<AttachmentModel>(
'Attachment',
{
id: {
allowNull: false,
autoIncrement: false,
type: DataTypes.UUID,
defaultValue: UUIDV4,
primaryKey: true,
unique: true,
},
path: {
type: DataTypes.STRING,
},
post_id: {
type: DataTypes.INTEGER,
key: "Post"
}
}
);
MAttachment.hasOne(MPost);

View File

@ -1,22 +1,37 @@
import { Sequelize, DataTypes, Optional, Model, UUIDV4 } from 'sequelize';
// import { Sequelize, DataTypes, Optional, Model, UUIDV4 } from 'sequelize';
import {
Association, DataTypes, HasManyAddAssociationMixin, HasManyCountAssociationsMixin,
HasManyCreateAssociationMixin, HasManyGetAssociationsMixin, HasManyHasAssociationMixin,
HasManySetAssociationsMixin, HasManyAddAssociationsMixin, HasManyHasAssociationsMixin,
HasManyRemoveAssociationMixin, HasManyRemoveAssociationsMixin, Model, ModelDefined, Optional,
Sequelize, InferAttributes, InferCreationAttributes, CreationOptional, NonAttribute, ForeignKey, BelongsTo, BelongsToGetAssociationMixin, UUIDV4, UUID
} from 'sequelize';
import { MUser, UserModel } from '@/model/sequelize/User';
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'db.sqlite'
});
interface AuthAttributes{
id: number;
token: string;
user_id: number;
};
interface AuthCreationAttributes extends Optional<Optional<AuthAttributes, 'id'>,'token'> {};
class AuthModel extends Model<AuthAttributes, AuthCreationAttributes>{
createdAt?: Date;
updatedAt?: Date;
token: any;
// declare title
// interface AuthAttributes{
// id: number;
// token: string;
// user_id: number;
// };
// interface AuthCreationAttributes extends Optional<Optional<AuthAttributes, 'id'>,'token'> {};
// class AuthModel extends Model<AuthAttributes, AuthCreationAttributes>{
// createdAt?: Date;
// updatedAt?: Date;
// token: any;
// // declare title
// }
class AuthModel extends Model<InferAttributes<AuthModel, { omit: 'user' }>, InferCreationAttributes<AuthModel, { omit: 'user' }>> {
declare id: CreationOptional<number>;
declare token: CreationOptional<string>;
declare user_id: number;
declare getUser: BelongsToGetAssociationMixin<UserModel>;
declare user:NonAttribute<UserModel>;
}
export const MAuth = sequelize.define<AuthModel>(
'Auth',
export const MAuth = AuthModel.init(
{
id: {
allowNull: false,
@ -34,5 +49,25 @@ export const MAuth = sequelize.define<AuthModel>(
key: "User"
}
// date: DataTypes.DATE,
},
{
tableName: 'Auths',
sequelize // passing the `sequelize` instance is required
}
);
);
MAuth.belongsTo(MUser, {
foreignKey:'user_id',
targetKey:'id',
as: 'user'
})
MUser.hasMany(MAuth, {
sourceKey: 'id',
foreignKey: 'user_id',
as: 'authtokens' // this determines the name in `associations`!
});
// MAuth.belongsTo(MUser, { targetKey: 'id' });
// MAuth.sync();
export { AuthModel }

View File

@ -1,4 +1,5 @@
import { Sequelize, DataTypes, Optional, Model } from 'sequelize';
import { MAttachment } from '@/model/sequelize/Attachment';
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'db.sqlite'
@ -29,4 +30,5 @@ export const MPost = sequelize.define<PostModel>(
title: DataTypes.STRING,
content: DataTypes.STRING,
}
);
);
MPost.hasMany(MAttachment);

View File

@ -0,0 +1,73 @@
import { BelongsToGetAssociationMixin, UUIDV4 } from 'sequelize';
import {
Association, DataTypes, HasManyAddAssociationMixin, HasManyCountAssociationsMixin,
HasManyCreateAssociationMixin, HasManyGetAssociationsMixin, HasManyHasAssociationMixin,
HasManySetAssociationsMixin, HasManyAddAssociationsMixin, HasManyHasAssociationsMixin,
HasManyRemoveAssociationMixin, HasManyRemoveAssociationsMixin, Model, ModelDefined, Optional,
Sequelize, InferAttributes, InferCreationAttributes, CreationOptional, NonAttribute, ForeignKey,
} from 'sequelize';
import { UserModel } from '@/model/sequelize/User';
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'db.sqlite'
});
class ResourceModel extends Model<InferAttributes<ResourceModel, { omit: 'owner' }>, InferCreationAttributes<ResourceModel, { omit: 'owner' }>>{
declare id: CreationOptional<string>;
declare path: string;
declare owner: NonAttribute<UserModel>;
declare getOwner: BelongsToGetAssociationMixin<UserModel>;
// user_id: number | undefined;
createdAt?: Date;
updatedAt?: Date;
// declare title
declare static associations: {
owner: Association<ResourceModel,UserModel>;
};
}
ResourceModel.init({
id: {
allowNull: false,
autoIncrement: false,
type: DataTypes.UUID,
defaultValue: UUIDV4,
primaryKey: true,
unique: true,
},
path: {
type: DataTypes.STRING
},
createdAt: {
type: DataTypes.DATE
},
updatedAt: {
type: DataTypes.DATE
}
},{
sequelize,
tableName: 'Resource'
});
// export const MResource = sequelize.define<ResourceModel>(
// 'Resource',
// {
// id: {
// allowNull: false,
// autoIncrement: false,
// type: DataTypes.UUID,
// defaultValue: UUIDV4,
// primaryKey: true,
// unique: true,
// },
// path: {
// type: DataTypes.STRING,
// },
// user_id: {
// type: DataTypes.INTEGER,
// key: "User"
// }
// }
// );
// UserModel.hasMany(MResource);
// ResourceModel.belongsTo(UserModel);

View File

@ -1,24 +1,40 @@
import { Sequelize, DataTypes, Optional, Model } from 'sequelize';
// import { Sequelize, DataTypes, Optional, Model } from 'sequelize';
import {
Association, DataTypes, HasManyAddAssociationMixin, HasManyCountAssociationsMixin,
HasManyCreateAssociationMixin, HasManyGetAssociationsMixin, HasManyHasAssociationMixin,
HasManySetAssociationsMixin, HasManyAddAssociationsMixin, HasManyHasAssociationsMixin,
HasManyRemoveAssociationMixin, HasManyRemoveAssociationsMixin, Model, ModelDefined, Optional,
Sequelize, InferAttributes, InferCreationAttributes, CreationOptional, NonAttribute, ForeignKey, BelongsTo, BelongsToGetAssociationMixin, UUIDV4, UUID
} from 'sequelize';
import { AuthModel } from '@/model/sequelize/Auth';
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: 'db.sqlite'
});
interface UserAttributes{
id: number;
username: string;
password: string;
};
interface UserCreationAttributes extends Optional<UserAttributes, 'id'>{};
class UserModel extends Model<UserAttributes, UserCreationAttributes>{
createdAt?: Date;
updatedAt?: Date;
username: string = "";
password: string = "";
id?:number;
// declare title
// interface UserAttributes{
// id: number;
// username: string;
// password: string;
// };
// interface UserCreationAttributes extends Optional<UserAttributes, 'id'>{};
// export class UserModel extends Model<UserAttributes, UserCreationAttributes>{
// createdAt?: Date;
// updatedAt?: Date;
// username: string = "";
// password: string = "";
// id?:number;
// // declare title
// }
export class UserModel extends Model<InferAttributes<UserModel>, InferCreationAttributes<UserModel>>{
declare id: number|null;
declare username: string;
declare password: string;
declare getAuths:HasManyGetAssociationsMixin<AuthModel>;
}
export const MUser = sequelize.define<UserModel>(
'User',
export const MUser = UserModel.init(
{
id: {
allowNull: false,
@ -35,5 +51,10 @@ export const MUser = sequelize.define<UserModel>(
allowNull: false,
type: DataTypes.STRING,
}
},
{
tableName: 'Users',
sequelize // passing the `sequelize` instance is required
}
);
);
MUser.sync();

View File

@ -0,0 +1,56 @@
import mysql2, { Connection, RowDataPacket, OkPacket, QueryError } from "mysql2";
import { getConnection } from "@/db";
import { Post, postPlaceholder } from "@/model/Models";
import { getPosts, IPost } from "@/controller/Post";
import { NextApiRequest, NextApiResponse } from "next";
import { MPost } from "@/model/sequelize/Post";
import { MAttachment } from "@/model/sequelize/Attachment";
import { validatePassword, hashPassword } from "@/util/Auth";
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'Post') {
let getAuth = () => {
try {
if (req.headers.authorization === undefined) {
throw "Basic Auth is required";
}
const authString = Buffer.from(req.headers.authorization.split(" ")[1], "base64").toString("utf8");
return authString.split(":");
} catch (error) {
res.status(500).json(error);
return;
}
};
const auth = getAuth() || ["", ""];
console.log(auth);
const username = auth[0];
const password = auth[1];
// console.log(req.body);
await MUser.sync();
await MAuth.sync();
let user = await MUser.findOne({ where: { username: username } });
if (user == undefined) {
res.status(401).json("User does not exist");
return;
}
if (!(await validatePassword(password, user.password))) {
res.status(401).json("Invalid password");
return;
}
let authtoken = await MAuth.findOne({ where: { user_id: user.id } });
if (authtoken == undefined) {
if (user.id != undefined) {
authtoken = await MAuth.create({ user_id: user.id });
}
}
res.status(200).json(authtoken);
}
}

View File

@ -1,57 +1,99 @@
import mysql2, { Connection, RowDataPacket, OkPacket, QueryError } from "mysql2";
// import mysql2, { Connection, RowDataPacket, OkPacket, QueryError } from "mysql2";
import { getConnection } from "@/db";
import { Post, postPlaceholder } from "@/model/Models";
// import { Post, postPlaceholder } from "@/model/Models";
import { getPosts, IPost } from "@/controller/Post";
import { NextApiRequest, NextApiResponse } from "next";
import { MPost } from "@/model/sequelize/Post";
import { MUser } from "@/model/sequelize/User";
import { MUser, UserModel } from "@/model/sequelize/User";
import { MAuth } from "@/model/sequelize/Auth";
import { cookies } from 'next/headers';
import { setCookie } from '@/util/Cookies';
import { DataType, Model, Sequelize, UUID } from "sequelize";
import { validatePassword, hashPassword } from "@/util/Auth";
function getAuth(req: NextApiRequest) {
if (req.headers.authorization === undefined) {
throw "Basic Auth is required";
}
const authString = Buffer.from(req.headers.authorization.split(" ")[1], "base64").toString("utf8");
return authString.split(":");
};
type UserCredentials = {
user: UserModel | undefined,
valid: boolean
}
async function verifyUserCredentials(req: NextApiRequest, res: NextApiResponse): Promise<UserCredentials | undefined> {
// let user = await MUser.findOne({ where: { username: username } });
const auth = getAuth(req) || ["", ""];
console.log(auth);
let credentials: UserCredentials = { user: undefined, valid: false }
const username = auth[0];
const password = auth[1];
// console.log(req.body);
await MUser.sync();
await MAuth.sync();
let user = await MUser.findOne({ where: { username: username } });
if (user == undefined) {
res.status(401).json("User does not exist");
return;
}
if (!(await validatePassword(password, user.password))) {
res.status(401).json("Invalid password");
return;
}
credentials.valid = true;
credentials.user = user;
return credentials;
}
async function GET(req: NextApiRequest, res: NextApiResponse) {
let a = req.cookies;
console.log(a);
let credentials = { userid: req.query.userid, token: req.query.token };
let authtoken = await MAuth.findOne({
where: {
token: credentials.token,
user_id: credentials.userid
}
});
if(authtoken){
// res.setHeader("cookie")
setCookie(res, 'auth', authtoken, { path: '/', maxAge: 2592000 });
res.status(200).end();
}
else{
res.status(401).end();
}
// console.log(a);
// res.status(200).json(authtokens);
}
async function POST(req: NextApiRequest, res: NextApiResponse) {
const credentials = await verifyUserCredentials(req, res);
if (!credentials || !credentials.valid || !credentials.user)
return;
const user = await MUser.findOne({ where: { username: credentials.user.username } });
if (!user)
return;
res.status(200).json(await MAuth.create({ user_id: user.id }));
}
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'GET') {
let getAuth = () => {
try {
if (req.headers.authorization === undefined) {
throw "Basic Auth is required";
}
const authString = Buffer.from(req.headers.authorization.split(" ")[1], "base64").toString("utf8");
return authString.split(":");
} catch (error) {
res.status(500).json(error);
return;
}
};
const auth = getAuth() || ["", ""];
console.log(auth);
const username = auth[0];
const password = auth[1];
// console.log(req.body);
await MUser.sync();
await MAuth.sync();
let user = await MUser.findOne({ where: { username: username } });
if (user == undefined) {
res.status(401).json("User does not exist");
return;
}
if (!(await validatePassword(password, user.password))) {
res.status(401).json("Invalid password");
return;
}
let authtoken = await MAuth.findOne({ where: { user_id: user.id } });
if (authtoken == undefined) {
if (user.id != undefined) {
authtoken = await MAuth.create({ user_id: user.id });
}
}
res.status(200).json(authtoken);
switch (req.method){
case 'GET':
GET(req, res); break;
case 'POST':
POST(req, res); break;
default:
res.status(404).end();
break;
}
}

View File

@ -1,42 +1,55 @@
import mysql2, { Connection, RowDataPacket, OkPacket, QueryError } from "mysql2";
import { getConnection } from "@/db";
// import { getConnection } from "@/db";
import { Post, postPlaceholder } from "@/model/Models";
import { getPosts, IPost } from "@/controller/Post";
import { NextApiRequest, NextApiResponse } from "next";
// import { MPost, MUser, MAuth } from "@/model/Models"
import { MPost } from "@/model/sequelize/Post";
// import { MPost } from "@/model/sequelize/Post";
// import { MAuth } from "@/model/sequelize/Auth";
import { MUser } from "@/model/sequelize/User";
import { MAuth } from "@/model/sequelize/Auth";
import { DataType, Model, Sequelize, UUID } from "sequelize";
import { validatePassword, hashPassword } from "@/util/Auth";
async function POST(req: NextApiRequest, res: NextApiResponse){
MUser.sync();
const username = req.body.username;
const password = req.body.password;
await MUser.sync()
var user = await MUser.findOne({ where: { username: username } });
if (user != undefined){
res.status(500).json("User with that username already exists");
return;
}
const hash = await hashPassword(password)
user = await MUser.create({
username: username,
password: hash
})
res.status(200).json(user);
return;
}
async function GET(req: NextApiRequest, res: NextApiResponse){
MUser.sync();
const username = req.body.username;
const password = req.body.password;
await MUser.sync()
var users = await MUser.findAll();
res.status(200).json(users);
return;
}
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'POST') {
const username = req.body.username;
const password = req.body.password;
await MUser.sync()
var user = await MUser.findOne({ where: { username: username } });
if (user != undefined){
res.status(500).json("User with that username already exists");
return;
}
const hash = await hashPassword(password)
user = await MUser.create({
username: username,
password: hash
})
res.status(200).json(user);
return;
POST(req,res);
}
if (req.method === 'GET') {
const username = req.body.username;
const password = req.body.password;
await MUser.sync()
var users = await MUser.findAll();
res.status(200).json(users);
return;
else if(req.method === 'GET'){
GET(req,res);
}
}

21
src/util/Cookies.ts Normal file
View File

@ -0,0 +1,21 @@
import { serialize, CookieSerializeOptions } from 'cookie';
import { NextApiResponse } from 'next'
/**
* This sets `cookie` using the `res` object
*/
export const setCookie = (
res: NextApiResponse,
name: string,
value: unknown,
options: CookieSerializeOptions = {}
) => {
const stringValue =
typeof value === 'object' ? 'j:' + JSON.stringify(value) : String(value)
if (typeof options.maxAge === 'number') {
options.expires = new Date(Date.now() + options.maxAge * 1000)
}
res.setHeader('Set-Cookie', serialize(name, stringValue, options))
}