Skip to content

Commit 22c56dc

Browse files
Merge pull request #2 from bleriotnoguia/develop
Develop
2 parents fef6d51 + 3acf9d0 commit 22c56dc

32 files changed

Lines changed: 3497 additions & 348 deletions

README.md

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# JavaScript.cm (built with AdonisJS, inspired by laravel.cm)
1+
# JavaScript.cm
22

3-
This repository contains the source code for the javascript.cm website ( javascript community in Cameroon ), inspired by laravel.cm. Laravel Cameroon is the largest community of PHP & Laravel developers residing in Cameroon.
3+
This repository contains the source code for the [javascript.cm](https://javascript.cm) website ( javascript community in Cameroon ), inspired by [laravel.cm](https://laravel.cm). Laravel Cameroon is the largest community of PHP & Laravel developers residing in Cameroon.
44

55
## Server Requirements
66

@@ -55,11 +55,12 @@ node ace serve --watch
5555

5656
## Features
5757

58-
- [ ] User Authentication
59-
- [ ] GitHub Authentication
58+
- [x] User Authentication
59+
- [x] GitHub Authentication
6060
- [ ] Twitter Integration
6161
- [ ] Article Management
62-
- [ ] Community Features
62+
- [ ] Forum
63+
- [ ] Discussions
6364
- [ ] Admin Dashboard
6465
- [ ] Telegram Notifications
6566

@@ -73,13 +74,22 @@ node ace serve --watch
7374
| `node ace migration:run` | Run database migrations |
7475
| `node ace migration:rollback` | Rollback migrations |
7576

77+
## Stack / Resources
78+
79+
- [AdonisJS](https://adonisjs.com/)
80+
- [React.js](https://react.dev/)
81+
- [Inertia.js](https://inertiajs.com/)
82+
- [TailwindCSS](https://tailwindcss.com/)
83+
- [MySQL](https://www.mysql.com/)
84+
- [Lucid ORM](https://lucid.adonisjs.com/)
85+
7686
## Contributing
7787

7888
Please read the contribution guide before creating an issue or sending a pull request.
7989

8090
## Security Vulnerabilities
8191

82-
If you discover a security vulnerability in the application, please send an email to support@laravel.cm.
92+
If you discover a security vulnerability in the application, please send an email to [support@javascript.cm](mailto:support@javascript.cm).
8393

8494
## License
8595

app/controllers/auth/login_controller.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,33 @@ import { loginValidator } from '#validators/login_validator'
22
import { HttpContext } from '@adonisjs/core/http'
33
import User from '#models/user'
44
import { errors } from '@adonisjs/auth'
5+
56
export default class LoginController {
67
async show({ inertia }: HttpContext) {
78
return inertia.render('auth/login')
89
}
910

1011
async login({ request, auth, response, session }: HttpContext) {
11-
const data = await loginValidator.validate(request.all())
12-
const user = await User.verifyCredentials(data.email, data.password)
13-
1412
try {
15-
await auth.use('web').login(user)
13+
// Validate the request data
14+
const data = await loginValidator.validate(request.all())
15+
16+
// Attempt to verify credentials
17+
const user = await User.verifyCredentials(data.email, data.password)
18+
19+
// Login the user
20+
await auth.use('web').login(user, data.remember)
21+
1622
return response.redirect().toRoute('dashboard')
1723
} catch (error) {
1824
if (error instanceof errors.E_INVALID_CREDENTIALS) {
1925
session.flash('errors', { form: 'Invalid credentials' })
2026
return response.redirect().back()
2127
}
22-
throw error
28+
29+
// Handle other errors
30+
session.flash('errors', { form: 'An error occurred during login' })
31+
return response.redirect().back()
2332
}
2433
}
2534

app/controllers/home_controller.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { HttpContext } from '@adonisjs/core/http'
2+
import Article from '#models/article'
3+
4+
export default class HomeController {
5+
async index({ inertia }: HttpContext) {
6+
const articles = await Article.query().where('is_published', true).preload('author')
7+
8+
return inertia.render('home', {
9+
stats: {
10+
members: 600,
11+
developers: 50,
12+
participation: 25,
13+
githubStars: 10,
14+
},
15+
articles: articles,
16+
})
17+
}
18+
}

app/middleware/silent_auth_middleware.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ import type { NextFn } from '@adonisjs/core/types/http'
99
*/
1010
export default class SilentAuthMiddleware {
1111
async handle(ctx: HttpContext, next: NextFn) {
12+
// Check authentication without redirecting
1213
await ctx.auth.check()
14+
1315
return next()
1416
}
1517
}

app/models/user.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { DateTime } from 'luxon'
2-
import { BaseModel, beforeSave, column, hasMany } from '@adonisjs/lucid/orm'
2+
import { BaseModel, column, hasMany } from '@adonisjs/lucid/orm'
33
import { compose } from '@adonisjs/core/helpers'
44
import hash from '@adonisjs/core/services/hash'
55
import { withAuthFinder } from '@adonisjs/auth/mixins/lucid'
66
import type { HasMany } from '@adonisjs/lucid/types/relations'
77
import Article from '#models/article'
8+
import { DbRememberMeTokensProvider } from '@adonisjs/auth/session'
89

910
const AuthFinder = withAuthFinder(() => hash.use('scrypt'), {
1011
uids: ['email'],
@@ -57,12 +58,7 @@ export default class User extends compose(BaseModel, AuthFinder) {
5758
@hasMany(() => Article)
5859
declare articles: HasMany<typeof Article>
5960

60-
@beforeSave()
61-
static async hashPassword(user: User) {
62-
if (user.$dirty.password) {
63-
user.password = await hash.make(user.password)
64-
}
65-
}
61+
static rememberMeTokens = DbRememberMeTokensProvider.forModel(User)
6662

6763
/**
6864
* Serialize the model for Inertia

config/auth.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const authConfig = defineConfig({
77
guards: {
88
web: sessionGuard({
99
useRememberMeTokens: true,
10+
rememberMeTokensAge: '1 year',
1011
provider: sessionUserProvider({
1112
model: () => import('#models/user'),
1213
}),

config/inertia.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const inertiaConfig = defineConfig({
1111
* Data that should be shared with all rendered pages
1212
*/
1313
sharedData: {
14+
appName: 'JavaScript Cameroun',
1415
auth: (ctx) => {
1516
return {
1617
user: ctx.auth.user,

database/migrations/1736839410875_create_users_table.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ export default class extends BaseSchema {
1616
table.boolean('is_admin').defaultTo(false)
1717
table.boolean('is_sponsor').defaultTo(false)
1818
table.timestamp('email_verified_at').nullable()
19-
table.string('remember_me_token').nullable()
2019
table.timestamps(true, true)
2120
})
2221
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { BaseSchema } from '@adonisjs/lucid/schema'
2+
3+
export default class extends BaseSchema {
4+
protected tableName = 'remember_me_tokens'
5+
6+
async up() {
7+
this.schema.createTable(this.tableName, (table) => {
8+
table.increments()
9+
table
10+
.integer('tokenable_id')
11+
.notNullable()
12+
.unsigned()
13+
.references('id')
14+
.inTable('users')
15+
.onDelete('CASCADE')
16+
17+
table.string('hash').notNullable().unique()
18+
table.timestamp('created_at').notNullable()
19+
table.timestamp('updated_at').notNullable()
20+
table.timestamp('expires_at').notNullable()
21+
})
22+
}
23+
24+
async down() {
25+
this.schema.dropTable(this.tableName)
26+
}
27+
}

database/seeders/user_seeder.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { BaseSeeder } from '@adonisjs/lucid/seeders'
2+
import User from '#models/user'
3+
4+
export default class UserSeeder extends BaseSeeder {
5+
async run() {
6+
// Create a test user
7+
await User.create({
8+
username: 'testuser',
9+
name: 'Test User',
10+
email: 'test@example.com',
11+
password: 'password123',
12+
isAdmin: true,
13+
isSponsor: false,
14+
})
15+
16+
// You can add more test users if needed
17+
await User.create({
18+
username: 'regularuser',
19+
name: 'Regular User',
20+
email: 'regular@example.com',
21+
password: 'password123',
22+
isAdmin: false,
23+
isSponsor: false,
24+
})
25+
26+
console.log('✅ Users seeded successfully')
27+
}
28+
}

0 commit comments

Comments
 (0)