DAILY NEWS

Stay Ahead, Stay Informed – Every Day

Advertisement
Part 2 Building an Authentication System from Scratch – Backend Setup


User Registration & Secure Password Hashing with bcrypt

In the previous article, we built the backend foundation by setting up Express.js, PostgreSQL, environment variables, and a clean layered architecture.

With the backend ready, it’s time to implement the first authentication feature—User Registration.

Although registration appears straightforward, it involves much more than simply storing user details in a database. A secure registration system must validate user input, prevent duplicate accounts, protect passwords, and ensure that sensitive information is never exposed.

In this article, we’ll build the complete registration workflow while following security best practices.

The registration process follows a layered architecture, where each layer has a single responsibility.

Client


Routes


Controller


Service


Repository


PostgreSQL

Enter fullscreen mode

Exit fullscreen mode

The overall workflow is:

The client submits the registration form.
The controller receives the request.
The service validates the data.
The repository checks whether the email already exists.
The password is securely hashed using bcrypt.
The user is stored in PostgreSQL.
A success response is returned to the client.

Instead of placing all the registration logic inside the controller, I divided the implementation into three layers.

Controller

Responsible only for:

Receiving the HTTP request
Calling the service layer
Returning the HTTP response

The controller should never contain business logic or database queries.

Service

The service contains the application’s business logic.

For registration, it is responsible for:

Validating the request
Checking whether the email already exists
Hashing the password
Calling the repository to save the user

This layer acts as the brain of the application.

Repository

The repository communicates directly with PostgreSQL.

Its responsibilities include:

Checking if a user already exists
Creating a new user
Executing SQL queries

Keeping SQL isolated inside repositories makes the application easier to maintain and test.

The controller receives the registration request and forwards the data to the service layer.

// Register Controller Screenshot Here

Enter fullscreen mode

Exit fullscreen mode

The controller itself performs very little work.

Its responsibility is simply to:

Extract the request body
Call the service
Return either a success or an error response

This keeps controllers lightweight and easy to understand.

The service contains the actual registration workflow.

// Register Service Screenshot Here

Enter fullscreen mode

Exit fullscreen mode

The registration service performs the following steps:

Check whether the email already exists.
Generate a secure password hash.
Create the user in PostgreSQL.
Return the newly created user.

Because all business rules live inside the service layer, future changes become much easier.

For example, adding email verification later would require changes only inside the service, without affecting controllers or repositories.

The repository is responsible only for database communication.

// Repository Screenshot Here

Enter fullscreen mode

Exit fullscreen mode

Typical repository functions include:

findByEmail()
createUser()

Keeping SQL queries isolated improves readability and keeps the service layer database-agnostic.

One of the biggest mistakes an application can make is storing passwords in plain text.

Imagine a database leak.

If passwords are stored as plain text, every user’s credentials become immediately visible.

Instead, passwords should always be transformed into a secure one-way hash before being stored.

This is exactly why we use bcrypt.

bcrypt is one of the most trusted password hashing libraries available for Node.js.

Unlike encryption, hashing is a one-way operation.

This means:

The original password cannot be recovered.
Even the application itself cannot view the user’s password.
Only password verification is possible.

When a user registers, bcrypt performs several operations internally.

Password


Generate Random Salt


Password + Salt


Multiple Hashing Rounds


Store Hash in Database

Enter fullscreen mode

Exit fullscreen mode

Each password receives its own randomly generated salt before hashing.

Because of this:

Two users with the same password will have completely different hashes.
Rainbow table attacks become ineffective.
Brute-force attacks become significantly slower due to bcrypt’s configurable cost factor.

During login, the user enters their password as plain text.

bcrypt then:

Reads the stored hash.
Extracts the embedded salt.
Hashes the entered password using the same salt.
Compares the generated hash with the stored hash.

If both hashes match, the user is successfully authenticated.

const isMatch = await bcrypt.compare(
enteredPassword,
storedHash
);

Enter fullscreen mode

Exit fullscreen mode

One of bcrypt’s biggest advantages is that developers never need to manually manage salts or compare hashes—the library handles the entire verification process securely.

Using bcrypt provides several important security advantages.

✅ Passwords are never stored in plain text.

✅ Every password uses a unique random salt.

✅ Identical passwords generate different hashes.

✅ Brute-force attacks become significantly slower.

✅ Rainbow table attacks are mitigated.

These features make bcrypt one of the industry standards for password protection.

Once the backend implementation was complete, I verified the registration API using Postman.

Request

POST /api/auth/register

Enter fullscreen mode

Exit fullscreen mode

{
“username”: “Sriya”,
“email”: “sriya@gmail.com”,
“password”: “Password123”
}

Enter fullscreen mode

Exit fullscreen mode

Response

{
“success”: true,
“user”: {
“id”: 1,
“username”: “Sriya”,
“email”: “sriya@gmail.com”
}
}

Enter fullscreen mode

Exit fullscreen mode

Notice that the response never includes the password or its hash.

Only non-sensitive user information is returned to the client.

Now that users can securely register and their passwords are safely stored, the next step is allowing them to authenticate.

In the next article, we’ll build the Login Flow, where we’ll:

Verify user credentials
Compare passwords using bcrypt
Generate JWT Access Tokens
Generate Refresh Tokens
Understand how JWT authentication works internally



Source link

Codex – a.k.a. ChatGPT’s AI Agent



Codex is OpenAI’s AI coding agent, and ChatGPT is the interface you can use to interact with it. That’s the difference.

As a software engineer, software development has gone through drastic shifts over the decades. We moved from assembly language to high-level programming languages, from waterfall to Agile, from on-premise infrastructure to cloud computing, and from manual deployments to DevOps and continuous delivery.

The next major shift is the emergence of AI coding agents.

Rather than simply generating code snippets, modern coding agents can understand an entire codebase, plan changes, execute them, run tests, fix issues, and explain their reasoning. One of the leading tools in this space is Codex.

What is Codex?

Codex is an AI-powered software engineering agent designed to help developers work directly with their source code.

Unlike traditional AI assistants that answer questions or generate isolated functions, Codex operates much more like another engineer on your team. It can:

Explore an existing repository
Understand project architecture
Make changes across multiple files
Execute commands
Run tests
Fix compilation errors
Refactor code
Generate documentation
Create pull-request-ready changes

Instead of asking “How do I implement JWT authentication?”, you can ask Codex:

“Implement JWT authentication across this Express application using our existing middleware patterns.”

Codex then performs the work inside your repository rather than simply describing how it could be done.

From AI Assistant to AI Engineer

Many developers have used AI chatbots to generate code snippets.

That workflow typically looks like this:

Developer


Copy code into ChatGPT


Receive code


Paste into IDE


Fix compilation errors


Repeat

Enter fullscreen mode

Exit fullscreen mode

Codex changes the workflow entirely.

Developer


Describe the task


Codex explores repository


Implements changes


Runs tests


Fixes issues


Produces ready-to-review changes

Enter fullscreen mode

Exit fullscreen mode

The interaction becomes goal-oriented instead of code-oriented.

Understanding the Entire Codebase

One of Codex’s biggest strengths is repository awareness.

Rather than treating every prompt independently, Codex understands:

project structure
frameworks
existing coding conventions
dependency management
architecture
naming conventions
testing framework
deployment configuration

For example, in a large Node.js monorepo, Codex can recognize:

apps/
packages/
shared/
infra/
docs/
.github/

Enter fullscreen mode

Exit fullscreen mode

It understands how these components interact and modifies only the areas relevant to the requested task.

This dramatically reduces the amount of context developers need to manually provide.

Working Like a Real Engineer

A typical software task rarely involves writing one function.

Consider a request such as:

“Add audit logging whenever an invoice is approved.”

A human engineer would likely:

locate the approval endpoint
identify the service layer
update the database model
modify unit tests
update integration tests
document the API
verify linting
run the test suite

Codex follows a remarkably similar workflow. Rather than generating a single function, it works through the complete implementation.

Skills and Project Memory

One of the most useful capabilities of Codex is its support for project-specific guidance.

Teams can provide instructions that describe:

coding standards
architectural principles
testing requirements
security practices
repository structure
naming conventions

This allows Codex to behave consistently across an organization.

For example, instructions may specify:

Always use dependency injection.
Never access the database directly from controllers.
Write unit tests before integration tests.
Use repository pattern.
Follow Domain-Driven Design boundaries.
Never commit generated files.

Instead of repeating these instructions in every prompt, Codex learns them from project configuration.

What is an AGENTS.md

Many teams create an AGENTS.md file that acts as an operating manual for AI coding agents. An AGENTS.md file can include:

project overview
architecture
folder structure
coding conventions
build commands
testing commands
deployment process
common pitfalls
review checklist

For example:

# Project Rules

– Node.js 22
– TypeScript only
– Use Prisma ORM
– No direct SQL
– Unit tests required
– Follow Clean Architecture
– Run npm test before completion

Enter fullscreen mode

Exit fullscreen mode

The better this document is maintained, the more consistently Codex performs.

Practical Use Cases

Codex excels at repetitive and complex engineering tasks.

Some examples I’ve used Codex for include:

Feature development

REST APIs
GraphQL resolvers
UI components
database migrations

Refactoring

rename services
split large classes
introduce dependency injection
improve architecture

Bug fixing

investigate failing tests
locate regressions
repair compilation errors
resolve lint issues

Documentation

generate API documentation
update README files
explain complex modules
document infrastructure

Testing

create unit tests
generate mocks
improve coverage
fix broken test suites

Infrastructure

AWS CDK
Terraform
GitHub Actions
Docker
Kubernetes

Strengths

Codex offers several advantages over traditional AI-assisted coding.

1. Repository Awareness

It understands your project’s structure instead of treating every prompt in isolation.

2. Multi-file Editing

Real-world features often require coordinated changes across many files. Codex can handle those changes in one workflow.

3. Command Execution

Codex can build projects, execute tests, run linters, and validate its own work.

4. Consistency

When provided with project instructions, it follows the team’s engineering standards.

5. Reduced Context Switching

Developers spend less time copying code into chat windows and more time reviewing completed work.

Am Not trusting AI Agents 100%

I am discussing the uses of Codex and yet, I still don’t trust it. Conflicting? Probably. Despite its capabilities, Codex (and all AI Agents) is not a replacement for seasoned software engineers.

Human judgment remains essential for:

system architecture
product design
business requirements
security decisions
trade-off analysis
stakeholder communication
technical leadership

The best results come from treating Codex as an engineering partner rather than an autonomous replacement.

AI coding agents represent a significant evolution in software development.

Just as integrated development environments replaced text editors, and CI/CD transformed software delivery, AI agents are reshaping how engineers interact with code.

Rather than focusing on writing every line manually, developers increasingly define objectives, review implementations, and guide architectural decisions while AI handles much of the repetitive engineering work.

Codex exemplifies this shift. It combines repository understanding, code generation, automated validation, and project-specific guidance into a workflow that feels less like using an autocomplete tool and more like collaborating with another engineer.

For organizations willing to invest in clear architecture, strong engineering practices, and well-maintained project documentation, AI coding agents like Codex can significantly accelerate development while allowing engineers to concentrate on solving the problems that require human creativity, judgment, and experience.

Best Practices

Teams adopting Codex tend to achieve better results when they:

Keep repositories well organized.
Maintain clear documentation.
Define coding standards.
Write comprehensive tests.
Provide architectural guidance through AGENTS.md.
Review AI-generated changes before merging.
Use small, well-defined tasks.
Encourage iterative collaboration rather than one-shot prompts.

These practices improve not only AI-generated code but also the overall quality of the software project.



Source link

The Codename One Game Builder: Draw The Level, Code The Rules


Friday’s release post introduced the Game Builder and promised a tutorial series. This post is the orientation that sits in front of those tutorials: what the Game Builder is, how its pieces fit together, and why it exists. The hands-on builds start Thursday.

What is Codename One? Codename One is an open-source framework for building native iOS, Android, desktop, and web apps from a single Java or Kotlin codebase. Learn more at codenameone.com.

Last week we shipped the com.codename1.gaming API: a game loop, sprites, scenes, pollable input, a low-latency sound pool, and Box2D physics, all running unchanged on every platform including iOS. That gave you the runtime. The missing half was authoring. Building a level purely in Java means dozens of new Sprite(…), setX, and setY calls you cannot see until you run them and must recompile to tweak. The Game Builder (PR #5253) replaces that with a visual editor and a plain-data level file.

Draw the level, code only the rules

The core idea is that a level is data, not code. You draw it in the editor, tag each object with the numbers your game needs (lives, value, speed), and the editor saves a small .game file. The runtime loads that file and realizes it into a scene of sprites. What is left for you to write is the part that is actually yours: the rules.

The editor is itself a Codename One app (Java 17) with three panels that matter: the Hierarchy of layers and objects, the Asset Library of art you stamp down, and the Inspector for the selected object’s transform and behavior values. Two Maven goals drive it:

mvn cn1:create-game-scene -DclassName=com.example.mygame.MyScene
mvn cn1:gamebuilder

Enter fullscreen mode

Exit fullscreen mode

create-game-scene writes an empty .game level and a companion Java class into your project; cn1:gamebuilder opens the editor on it. Both goals are gated to Java 17.

One editor, three kinds of game

The same editor and the same .game format author three modes, and the runtime realizes each one without your code changing shape:

2D, for side-scrollers and top-down games. A tile grid, layers for draw order, and sprites.

Board, an isometric projection for card and tabletop games, where pieces are data-driven elements on a board.

3D, for first-person and overhead 3D, with terrain you sculpt and a per-game-type preview (open, flight, race, or dungeon) complete with a radar.

The three tutorials each build one of these, so the range is easiest to see as three finished games:

The 3D editor sculpts terrain directly: height, holes, walls, pluggable surface materials, and smooth interpolated slopes, all previewed in the form factor of the game you are making.

From .game file to running game

The data model lives in com.codename1.gaming.level: GameLevel, GameElement, Layer, TileLayer, AssetCatalog, and IsoProjection, with JSON load and save across all three modes. Your companion class loads the level and the editor regenerates the wiring for every object you named, so renaming or adding an object in the Inspector just updates your fields. The constructor and the update loop are yours:

public class MyScene extends GameSceneView {
public MyScene(AssetCatalog catalog) {
super(loadLevel(), catalog); // realizes the level into a Scene of Sprites
setArcadeBehavior(true); // built-in run/jump/gravity/patrol/pickups (2D)
}

private static GameLevel loadLevel() throws java.io.IOException {
return GameLevel.load(Display.getInstance()
.getResourceAsStream(MyScene.class, “/MyScene.game”));
}

@Override
protected void onUpdate(double deltaSeconds) {
// your rules go here
}
}

Enter fullscreen mode

Exit fullscreen mode

GameSceneView is a GameView, which is a regular Codename One Component, so you drop it into a Form and call start() to begin the loop. Because you edit onUpdate and not the generated block, re-running cn1:gamebuilder to tweak the level keeps your logic intact.

Large worlds that stream

Some games outgrow a single hand-drawn level. The Game Builder ships a streaming engine for large and open worlds, and the editor has a Large World mode that edits and previews the active region. The pieces are a pluggable Material and MaterialRegistry; a chunked StreamingTerrain with a ChunkProvider, LRU paging, and support for negative coordinates; variable-size TerrainFeature objects for walls, ramps, and platforms; and loadable Region and RegionProvider types stitched into a GameWorld that streams neighboring regions in seamlessly. A GameLevel can persist an optional GameWorld, so a streaming world saves and loads like any other level.

A note on beta

The Game Builder and the high-level gaming APIs are beta. They work, the tutorials are real games you can build start to finish, and they run on every platform. What is not yet settled is the shape: the editor’s interactions, the API surface, and the asset workflow are all things we expect to refine. That is exactly why we are shipping it now and writing about it: we want your reports. If the editor fights you, an API reads wrong, or an asset will not import the way you expect, file it on the issue tracker with the project or asset attached.

Where to go next

The three tutorials build a real game each, in increasing order of ambition:

Thursday. . It covers the part most tutorials skip: bringing in real art and slicing an animated sprite sheet.

The Thursday after. . Cards become data-driven elements on a felt table.

The Thursday after that. . Sculpt terrain and scale up to streaming worlds.

Start with Thursday’s platformer; it introduces every moving part you will reuse in the other two.



Source link