finally got the associations to work through black magic

This commit is contained in:
Andreas Schaafsma 2024-06-13 07:03:38 +02:00
parent c72ac5e67f
commit 21e31d0ee4
16 changed files with 98 additions and 144 deletions

View File

@ -1,14 +1,12 @@
'use server'
import { APIError, attemptAPIAction } from "@/util/api/error";
import { Auth, Post, PostTag, Tag, User } from "@/model/Models";
import { sequelize, Bucket, Auth, Post, PostTag, Tag, User, dbSync } from "@/model/Models";
import { cookies } from "next/headers";
import { Attachment } from "@/model/Attachment";
import { UUID, randomUUID } from "crypto";
import { mkdir, mkdirSync, writeFile } from "fs";
import { Bucket } from "@/model/Bucket";
import { where } from "@sequelize/core";
import { PostBucket } from "@/model/Post";
@ -37,28 +35,28 @@ async function writeFilesToBucket(uuid: UUID, files:any[]) {
async function addToPost(postid:number):Promise<UUID>
{
const post = await Post.findOne({where: {id:postid}, include: {association: Post.associations.postBuckets}});
if (!post) throw new APIError({ status: 500, responseText: "invalid postid" });
const bucket = await Bucket.create({id:randomUUID()});
const bucketPost = await PostBucket.create({bucketId: bucket.id, postId: postid})
Post.sync();
const post = await Post.findOne({where: {id:postid}});
console.log(bucketPost);
return bucket.id
if (!post) throw new APIError({ status: 500, responseText: "invalid postid" });
const bucket = await post.createBucket({id:randomUUID()});
// const bucketPost = await Post.associations.postBuckets.create({bucketId: bucket.id, postId: postid})
// console.log(bucketPost);
return bucket.id;
}
async function addToBucket(bucketid:number):Promise<UUID> {
const bucket = await Bucket.findOne({where: {id: bucketid}});
if (!bucket) throw new APIError({ status: 500, responseText: "invalid bucketid" });
return bucket.id
return bucket.id;
}
async function tryCreateAttachment(request: Request) {
// Make sure the DB is ready
await Attachment.sync();
await Bucket.sync();
await Post.sync();
await dbSync;
// Prepare data
const formData = await request.formData();
const requestData:string | Object | undefined = formData.get('data')?.valueOf();

View File

@ -1,7 +1,7 @@
'use server'
import { APIError, attemptAPIAction } from "@/util/api/error";
import { Auth, Post, PostTag, Tag, User } from "@/model/Models";
import { Auth, Post, PostTag, Tag, User, dbSync } from "@/model/Models";
import { cookies } from "next/headers";
@ -9,9 +9,7 @@ import { cookies } from "next/headers";
async function tryCreatePost(request: Request) {
// Make sure the DB is ready
await PostTag.sync();
await Tag.sync();
await Post.sync();
const sync = await dbSync;
// Prepare data
const requestBody = await request.json();

View File

@ -4,17 +4,14 @@ import { cookies } from "next/headers";
import { APIError} from "@/util/api/error"
import { UserAuth, parseBasicAuth, getAssociatedUser } from "@/util/api/user"
import { Auth, Post, Tag, User } from "@/model/Models";
import { Project } from "@/model/Project";
import { Attachment } from "@/model/Attachment";
import { Bucket } from "@/model/Bucket";
import { DBState } from "@/model/DBState";
import { Attachment, Auth, Bucket, DBState, Post, PostTag, Project, Tag, User, UserPerms,dbSync,sequelize} from "@/model/Models";
import Sequelize, { DataTypes } from "@sequelize/core";
import { SqliteColumnsDescription, SqliteDialect, SqliteQueryInterface } from "@sequelize/sqlite3";
import { hashPassword } from "@/util/Auth";
async function seedDatabase(queryInterface:SqliteQueryInterface<SqliteDialect>){
const password = await hashPassword('changeme');
const project = await Project.findOne({where: {
readableIdentifier: 'blog'
@ -43,21 +40,10 @@ async function seedDatabase(queryInterface:SqliteQueryInterface<SqliteDialect>){
}
async function trySetup(request:Request){
await dbSync;
const sequelize = await new Sequelize({
dialect: SqliteDialect,
storage: 'db.sqlite'
})
const queryInterface = sequelize.queryInterface
// await User.sync();
await Auth.sync();
await User.sync();
await Attachment.sync();
await Bucket.sync();
await Project.sync()
await Tag.sync();
await Post.sync();
await DBState.sync();
const version = (await DBState.findAll()).sort((a,b)=> ((a.version > b.version) ? 1 : -1)).map(a=>a.version)[0];

View File

@ -10,15 +10,16 @@
import { APIError } from "@/util/api/error";
import { UserAuth } from "@/util/api/user";
import { UserPerms, User, Auth } from "@/model/Models"; // Do not alter "unused" imports, they are required to perform the nescessairy includes on the User model
import { Attachment, Auth, Bucket, DBState, Post, PostTag, Project, Tag, User, UserPerms,dbSync,sequelize} from "@/model/Models";
import { hashPassword } from "@/util/Auth";
import { addUserScopes } from "@/model/User";
// Attempt to register a new User
async function attemptRegister(request:Request){
async function attemptRegister(request:Request){
// Sync db
await dbSync;
// Sync User model
User.sync();
// Get request body
const requestBody:Partial<UserAuth> = await request.json();
// Handle edgecases
@ -73,6 +74,7 @@ export async function POST(request:Request){
}
async function attemptGetUsers(request:Request){
await dbSync;
// Get users with scopes applied
const users = await User.withScope(['defaultScope','withPerms','withAuthtokens']).findAll();
return new Response(

View File

@ -34,9 +34,3 @@ export class APIKey extends Model<InferAttributes<APIKey>, InferCreationAttribut
declare updatedAt: CreationOptional<Date>;
}
const sequelize = new Sequelize({
dialect: SqliteDialect,
storage: 'db.sqlite',
models: [APIKey]
});

View File

@ -26,10 +26,5 @@ export class Attachment extends Model<InferAttributes<Attachment>, InferCreation
declare static associations: {
bucket: Association<Bucket, Attachment>;
};
}
const sequelize = new Sequelize({
dialect: SqliteDialect,
storage: 'db.sqlite',
models: [Attachment]
})

View File

@ -46,9 +46,3 @@ export class Auth extends Model<InferAttributes<Auth>, InferCreationAttributes<A
};
}
const sequelize = new Sequelize({
dialect: SqliteDialect,
storage: 'db.sqlite',
models: [Auth]
});

View File

@ -1,4 +1,4 @@
import { Association, BelongsToGetAssociationMixin, BelongsToManyGetAssociationsMixin, DataTypes, ForeignKey, InferAttributes, InferCreationAttributes, Model, NonAttribute, Sequelize, sql } from "@sequelize/core";
import { Association, BelongsToGetAssociationMixin, BelongsToManyAddAssociationMixin, BelongsToManyCreateAssociationMixin, BelongsToManyGetAssociationsMixin, BelongsToManyRemoveAssociationMixin, BelongsToManySetAssociationsMixin, DataTypes, ForeignKey, InferAttributes, InferCreationAttributes, Model, NonAttribute, Sequelize, sql } from "@sequelize/core";
import { Post } from "./Post";
import { SqliteDialect } from '@sequelize/sqlite3';
@ -14,19 +14,14 @@ export class Bucket extends Model<InferAttributes<Bucket>, InferCreationAttribut
declare id: UUID
/** Defined by {@link Post.buckets} */
declare bucketPosts?:NonAttribute<Post>[];
declare posts?:NonAttribute<Post>[];
/** Defined by {@link Attachment.bucket} */
declare attachments?:NonAttribute<Attachment>[];
declare static associations: {
bucketPosts: Association<Post, Bucket>;
posts: Association<Post, Bucket>;
attachments: Association<Attachment, Bucket>;
};
}
const sequelize = new Sequelize({
dialect: SqliteDialect,
storage: 'db.sqlite',
models: [Bucket]
})

View File

@ -32,9 +32,3 @@ export class DBState extends Model<InferAttributes<DBState>, InferCreationAttrib
}
const sequelize = new Sequelize({
dialect: SqliteDialect,
storage: 'db.sqlite',
models: [DBState]
});

View File

@ -1,15 +1,29 @@
import { User } from './User';
import { Auth } from './Auth';
import { UserPerms } from './UserPerms';
import { Post } from './Post';
import { Tag } from './Tag';
import { Attachment } from './Attachment';
import { Bucket } from './Bucket';
import { DBState } from './DBState';
import { Post, PostBucket } from './Post';
import { PostTag } from './PostTag';
import { Project } from './Project';
import { Tag } from './Tag';
import { User, addUserScopes } from './User';
import { UserPerms, addUserPermsScopes } from './UserPerms';
import { SqliteDialect } from '@sequelize/sqlite3';
import Sequelize from '@sequelize/core';
User.sync();
Auth.sync();
UserPerms.sync();
PostTag.sync();
Tag.sync();
Post.sync();
export { User, Auth, UserPerms, Post, Tag, PostTag }
const sequelize = new Sequelize({
dialect: SqliteDialect,
storage: 'db.sqlite',
models: [Auth, Attachment, Bucket, DBState, Post, PostBucket, PostTag, Project, Tag, User, UserPerms],
});
const dbSync = (async ()=> await sequelize.sync())().then(()=>{
addUserScopes();
addUserPermsScopes();
});
export { sequelize, dbSync, Auth, Attachment, Bucket, DBState, Post, PostBucket, PostTag, Project, Tag, User, UserPerms }

View File

@ -1,4 +1,4 @@
import { Association, BelongsToGetAssociationMixin, BelongsToManyAssociation, BelongsToManyCreateAssociationMixin, CreationOptional, DataTypes, ForeignKey, InferAttributes, InferCreationAttributes, Model, NonAttribute, Sequelize } from "@sequelize/core";import { User } from "./User";
import { Association, BelongsToGetAssociationMixin, BelongsToManyAddAssociationMixin, BelongsToManyAssociation, BelongsToManyCreateAssociationMixin, BelongsToManyGetAssociationsMixin, BelongsToManyRemoveAssociationMixin, BelongsToManySetAssociationsMixin, CreationOptional, DataTypes, ForeignKey, InferAttributes, InferCreationAttributes, Model, NonAttribute, Sequelize } from "@sequelize/core";import { User } from "./User";
import { SqliteDialect } from '@sequelize/sqlite3';
import { Attribute, AutoIncrement, BelongsTo, BelongsToMany, CreatedAt, Default, HasMany, NotNull, PrimaryKey, Unique, UpdatedAt } from "@sequelize/core/decorators-legacy";
@ -49,11 +49,17 @@ export class Post extends Model<InferAttributes<Post>, InferCreationAttributes<P
@BelongsToMany(()=>Tag, { through: { model: ()=>PostTag, unique: false}, inverse: {as: 'taggedPosts'} })
declare postTags?:NonAttribute<Tag[]>;
@BelongsToMany(()=>Bucket,{through: { model: ()=> PostBucket, unique: false}, inverse:{as: 'bucketPosts'}, foreignKey: 'postId', otherKey: 'bucketId'})
declare postBuckets:NonAttribute<Bucket[]>;
@BelongsToMany(()=>Bucket,{through: {model:'PostBucket'}, throughAssociations: {
fromSource: 'postPostBuckets',
toSource: 'post',
fromTarget: 'postBucketPosts',
toTarget: 'PostBucket',
}, inverse:{as: 'posts'}, foreignKey: 'postId', otherKey: 'bucketId'})
declare buckets?:NonAttribute<Bucket[]>;
declare getUser: BelongsToGetAssociationMixin<User>;
declare static associations: {
@ -62,16 +68,25 @@ export class Post extends Model<InferAttributes<Post>, InferCreationAttributes<P
postBuckets: Association<Bucket, Post>
postTags: Association<Tag, Post>;
};
declare getUser: BelongsToGetAssociationMixin<User>;
declare getBuckets: BelongsToManyGetAssociationsMixin<Bucket>;
declare setBuckets: BelongsToManySetAssociationsMixin<Bucket,Bucket['id']>;
declare addBucket: BelongsToManyAddAssociationMixin<Bucket,Bucket['id']>;
declare addBuckets: BelongsToManyAddAssociationMixin<Bucket,Bucket['id']>;
declare removeBucket: BelongsToManyRemoveAssociationMixin<Bucket,Bucket['id']>;
declare removeBuckets: BelongsToManyRemoveAssociationMixin<Bucket,Bucket['id']>;
declare createBucket: BelongsToManyCreateAssociationMixin<Bucket>;
}
export class PostBucket extends Model<InferAttributes<PostBucket>, InferCreationAttributes<PostBucket>>{
export class PostBucket extends Model<InferAttributes<PostBucket>, InferCreationAttributes<PostBucket>> {
declare postId: number;
declare bucketId: UUID;
}
const sequelize = new Sequelize({
dialect: SqliteDialect,
storage: 'db.sqlite',
models: [Post, PostBucket]
})
declare post?:NonAttribute<Post>
declare bucket?:NonAttribute<Bucket>
PostBucket.sync();
}

View File

@ -11,10 +11,5 @@ class PostTag extends Model<InferAttributes<PostTag>,InferCreationAttributes<Pos
declare tagId:number;
}
const sequelize = new Sequelize({
dialect: SqliteDialect,
storage: 'db.sqlite',
models: [PostTag]
})
export { PostTag }

View File

@ -17,9 +17,3 @@ export class Project extends Model<InferAttributes<Project>, InferCreationAttrib
};
}
const sequelize = new Sequelize({
dialect: SqliteDialect,
storage: 'db.sqlite',
models: [Project]
})

View File

@ -18,9 +18,3 @@ export class Tag extends Model<InferAttributes<Tag>, InferCreationAttributes<Tag
posts: Association<Post, Tag>;
};
}
const sequelize = new Sequelize({
dialect: SqliteDialect,
storage: 'db.sqlite',
models: [Tag]
})

View File

@ -22,9 +22,7 @@ type UserCreationAttributes = {
password:string;
perms?:Partial<InferAttributes<UserPerms>>
}
export class User extends Model<InferAttributes<User>, InferCreationAttributes<User>>{
@Attribute(DataTypes.INTEGER)
@PrimaryKey
@AutoIncrement
@ -63,24 +61,16 @@ export class User extends Model<InferAttributes<User>, InferCreationAttributes<U
};
}
const sequelize = new Sequelize({
dialect: SqliteDialect,
storage: 'db.sqlite',
models: [User]
});
User.addScope('defaultScope',{
attributes: {
exclude: ['password', 'createdAt', 'updatedAt'],
}
});
User.addScope('withPerms',{
include: [{association: 'perms' }]
})
User.addScope('withAuthtokens',{
include: [{association: 'authtokens'}]
})
export function addUserScopes(){
User.addScope('defaultScope',{
attributes: {
exclude: ['password', 'createdAt', 'updatedAt'],
}
});
User.addScope('withPerms',{
include: [{association: 'perms' }]
})
User.addScope('withAuthtokens',{
include: [{association: 'authtokens'}]
})
}

View File

@ -26,13 +26,7 @@ export class UserPerms extends Model<InferAttributes<UserPerms>, InferCreationAt
}
const sequelize = new Sequelize({
dialect: SqliteDialect,
storage: 'db.sqlite',
models: [UserPerms],
});
export function addUserPermsScopes(){
UserPerms.addScope('defaultScope',{
attributes: {
@ -43,4 +37,6 @@ UserPerms.addScope('withTimestamps',{
attributes: {
include: ['createdAt', 'updatedAt'],
}
});
});
}