Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
499a0ea
change providerEndpouint to providername
honjes Jan 29, 2025
fada10b
change enum to contain names not endpoints
honjes Jan 29, 2025
117f692
change site to provider providerName instead of endpoint
honjes Jan 29, 2025
aecb548
make some changes to complie with eslint rules
honjes Jan 29, 2025
a999b79
code: move macro to setup
honjes Jan 29, 2025
94b6ad2
fix: use function to compute token
honjes Jan 29, 2025
13614d2
code: remove useless route
honjes Jan 29, 2025
2e0ee7e
code: clean up User class
honjes Jan 29, 2025
2db43fc
fix: endpoint now gets computed from provierName
honjes Jan 29, 2025
7a90d11
feat: add function to stringify a userObject to make it smaler
honjes Jan 29, 2025
ec55e63
add db initalastion to readme and dockerfile
honjes Jan 29, 2025
ab26d0e
add env creation to readme
honjes Jan 29, 2025
903c924
code: remove dev consolelogs
honjes Jan 29, 2025
d91ed22
feat: add util function to handle webIds
honjes Jan 29, 2025
a5dbbf8
code: change userName variable to username
honjes Jan 29, 2025
1261caa
code: use new util function
honjes Jan 29, 2025
0eacace
fix: use new function to check for webId
honjes Jan 29, 2025
f0beb1b
code: add prefix to posts to make routes esyer
honjes Jan 29, 2025
30d2da6
code: add exception for _ to eslint
honjes Jan 29, 2025
bea0dfc
feat: add check for memoryWebids to util
honjes Jan 29, 2025
9543d04
feat: add followers table
honjes Jan 29, 2025
b25eef6
add webId and ProviderWebId directly to userClass
honjes Jan 29, 2025
730147f
feat: add function to save following to Pod
honjes Jan 29, 2025
357f5bf
code: move PodProvider Types to own file and unify them
honjes Jan 29, 2025
eaf495d
feat: add route that allows users to follow eachother
honjes Jan 29, 2025
3a3bb2a
add routes to got folllowed users and following users
honjes Jan 29, 2025
91139b2
fix: recreate the right note creation type
honjes Jan 30, 2025
4072f22
code: make follow creation route post
honjes Jan 30, 2025
4358d7a
code: add documentation for activityPods class
honjes Jan 30, 2025
bf24f01
code: remove unused import
honjes Jan 30, 2025
98ddaaa
code: reorder function params to make them more simular
honjes Jan 30, 2025
9411bed
add api route to unfollow a user
honjes Jan 30, 2025
d634a85
code: make use of providerWebId
honjes Jan 30, 2025
c0d3842
code: add descriptive comment
honjes Jan 30, 2025
944bf01
feat: change styling of postheader
honjes Jan 30, 2025
6152e2d
code: moving handleError to util functions
honjes Jan 31, 2025
4b11305
code: make type for followUnfollow Request
honjes Jan 31, 2025
d9e5e12
code: move errors to api to have them in one place
honjes Jan 31, 2025
fc9dcef
feat: Follow Request now directly inherits UserTable.
honjes Jan 31, 2025
18122ab
code: remove double apiTypes
honjes Jan 31, 2025
5ced2b5
code: move types to api file
honjes Jan 31, 2025
e544ddb
feat: add store that hold followers and following users
honjes Jan 31, 2025
2eb1d73
code: add linting command to api and exclude build dirs
honjes Jan 31, 2025
5a4c995
feat: make follow and unfollow request return user
honjes Jan 31, 2025
1228757
code: make user icon logout for dev
honjes Jan 31, 2025
e9aa891
feat: make apirequest work with new responses
honjes Jan 31, 2025
8aa978a
feat: make it possible to follow user
honjes Jan 31, 2025
061d58a
code: remove unused import
honjes Jan 31, 2025
b2126fb
code: make scripts more descriptive
honjes Jan 31, 2025
541b9b1
code: format file with prettier
honjes Jan 31, 2025
235bfcb
feat: add action to test for eslint, prettier and test compliance
honjes Jan 31, 2025
04275c1
fix: make scripts check all files in folder
honjes Jan 31, 2025
aba1bc0
fix: make eslint and prettier ignore build files
honjes Jan 31, 2025
55a9c2c
code: run prettier
honjes Jan 31, 2025
fe0230e
fix: make action use the bun scripts
honjes Jan 31, 2025
5d16c12
fix: typo
honjes Jan 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: checks

on:
pull_request:
branches:
- master
- dev
push:
branches:
- master

jobs:
linting:
name: linting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2

# run eslint and prettier on the frontend and api
- run: bun install && bun lint && bun format:check
working-directory: ./frontend
- run: bun install && bun format:check
working-directory: ./api
testing:
name: testing
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2

# run tests on the api
- run: bun install && bun test
working-directory: ./api
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ Currently optimised mobile devices are:

#### Running the api
- go into the directory `cd api`
- copy the `.env.example` file to `.env` and fill in the values
- run `bun install` to install the dependencies
- run `bun drizzle:push` to push the database schema to the database
- run `bun dev` to start the api

#### Running the frontend
Expand Down
34 changes: 27 additions & 7 deletions api/eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,32 @@
import globals from "globals";
import pluginJs from "@eslint/js";
import tseslint from "typescript-eslint";

import globals from 'globals'
import pluginJs from '@eslint/js'
import tseslint from 'typescript-eslint'

/** @type {import('eslint').Linter.Config[]} */
export default [
{files: ["**/*.{js,mjs,cjs,ts}"]},
{languageOptions: { globals: globals.browser }},
{ files: ['**/*.{js,mjs,cjs,ts}'] },
{ languageOptions: { globals: globals.browser } },
pluginJs.configs.recommended,
...tseslint.configs.recommended,
];
{
name: 'app/files-to-ignore',
ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**', 'pm2.config.js']
},
{
rules: {
'no-unused-vars': ['off'],
'@typescript-eslint/no-unused-vars': [
'error',
{
args: 'all',
argsIgnorePattern: '^_',
caughtErrors: 'all',
caughtErrorsIgnorePattern: '^_',
destructuredArrayIgnorePattern: '^_',
varsIgnorePattern: '^_',
ignoreRestSiblings: true
}
]
}
}
]
6 changes: 5 additions & 1 deletion api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
"test": "bun test",
"drizzle:push": "drizzle-kit push",
"drizzle:migrate": "drizzle-kit migrate",
"drizzle:generate": "drizzle-kit generate"
"drizzle:generate": "drizzle-kit generate",
"lint": "bunx eslint .",
"lint:fix": "bunx eslint --fix .",
"format": "bunx prettier . --write",
"format:check": "prettier --check ."
},
"type": "module",
"devDependencies": {
Expand Down
39 changes: 30 additions & 9 deletions api/src/db/schema.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,61 @@
import { relations, eq, sql } from 'drizzle-orm'
import { relations, sql } from 'drizzle-orm'
import { boolean, text, serial, pgTable as table, timestamp, integer, pgView } from 'drizzle-orm/pg-core'

export const users = table('users', {
id: serial().primaryKey(),
name: text().notNull(),
displayName: text('display_name').notNull().unique(),
webId: text('web_id').notNull().unique(),
email: text('email').notNull().unique(),
providerEndpoint: text('provider_endpoint').notNull(),
providerName: text('provider_name').notNull() // This is done so there is no import here. It crashes the drizzle:push command
})

export const usersRelations = relations(users, ({one}) => ({
posts: one(posts),
export const usersRelations = relations(users, ({ many }) => ({
posts: many(posts),
followers: many(users)
}))

export const followers = table('followers', {
followerId: integer('follower_id')
.notNull()
.references(() => users.id),
followedId: integer('followed_id')
.notNull()
.references(() => users.id)
})

export const posts = table('posts', {
id: serial().primaryKey(),
content: text().notNull(),
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow(),
isPublic: boolean('is_public').notNull(),
authorId: integer('author_id').notNull().references(() => users.id),
authorId: integer('author_id').notNull()
})

export const postsRelations = relations(posts, ({ one }) => ({
author: one(users, {
fields: [posts.authorId],
references: [users.id]
})
}))

// Views
export const postsView = pgView('posts_view', {
id: serial().primaryKey(),
content: text().notNull(),
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow(),
isPublic: boolean('is_public').notNull(),
authorId: integer('author_id').notNull().references(() => users.id),
authorName: text("author_name").notNull(),
authorId: integer('author_id')
.notNull()
.references(() => users.id),
authorName: text('author_name').notNull(),
authorWebId: text('author_web_id').notNull().unique(),
authorProviderEndpoint: text('author_provider_endpoint').notNull(),
authorProviderEndpoint: text('author_provider_endpoint').notNull()
}).as(sql`SELECT
posts.*,
users.name as author_name,
users.web_id as author_web_id,
users.provider_endpoint as author_provider_endpoint
users.provider_name as author_provider_name
FROM posts
INNER JOIN users on posts.author_id = users.id
WHERE posts.is_public = true`)
64 changes: 32 additions & 32 deletions api/src/decorater/User.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,52 @@
import type { SelectUsers } from "../types"
import { encodeWebId } from '@/util/user'
import { podProviderEndpoint, ViablePodProvider, type SelectUsers } from '../types'

export default class User {
userId: number
userName: string
token: string
endpoint: string
userId: number = 0
username: string = ''
token: string = ''
provider: string = ''
endpoint: string = ''
webId: string = ''
providerWebId: string = ''

constructor(dbUser?: SelectUsers, token?: string) {
this.userId = 0
this.userName = ''
this.token = ''
this.endpoint = ''

if (dbUser) {
this.userId = dbUser.id
this.userName = dbUser.name
this.endpoint = dbUser.providerEndpoint
this.username = dbUser.name
this.provider = dbUser.providerName
this.computeValues()
}
if (token) {
this.token = token
}
}

loadUser(oldUser: User) {
this.userId = oldUser.userId
this.userName = oldUser.userName
this.token = oldUser.token
this.endpoint = oldUser.endpoint
loadUser(oldUser: string) {
const newUser = JSON.parse(oldUser)
this.userId = newUser.userId
this.username = newUser.username
this.token = newUser.token
this.provider = newUser.provider
this.computeValues()
}

getWebId() {
return `${this.endpoint}/${this.userName}`
private computeValues() {
this.endpoint = podProviderEndpoint[this.provider as ViablePodProvider]
this.webId = encodeWebId(this)
this.providerWebId = this.endpoint + '/' + this.username
}

setUser(userId: number, userName: string, token: string, endpoint: string) {
this.userId = userId
this.userName = userName
this.token = token
this.endpoint = endpoint
}

setUsername(userName: string) {
const userIdSplit = userName.split('/')
this.userName = userName
this.endpoint = userIdSplit[userIdSplit.length - 2]
getWebId() {
return encodeWebId(this)
}

setToken(token: string) {
this.token = token
toString() {
return JSON.stringify({
userId: this.userId,
username: this.username,
token: this.token,
provider: this.provider
})
}
}
20 changes: 2 additions & 18 deletions api/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,14 @@
import { Elysia } from 'elysia'
import { drizzle } from 'drizzle-orm/node-postgres'
import { _createPost, _selectUsers } from './types'
import { postsPlugin, authPlugin, setupPlugin } from './routes'
import { postsPlugin, authPlugin, setupPlugin, usersPlugin } from './routes'

export const db = drizzle({ connection: process.env.DB_URL || '', casing: 'snake_case' })

export const app = new Elysia()
.use(setupPlugin)
.macro({
isSignedIn: enabled => {
if (!enabled) return

return {
async beforeHandle({ headers: { auth }, jwt, error, user }) {
const authValue = await jwt.verify(auth)
if (!authValue) {
return error(401, 'You must be signed in to do that')
} else {
user.loadUser(JSON.parse(authValue.user as string))
}
}
}
}
})
.use(authPlugin)
.use(postsPlugin)
.use(usersPlugin)
.listen(process.env.API_PORT || 8796)

console.info(`Listening on port ${process.env.API_PORT}`)
Expand Down
Loading