Skip to content

Commit 5a6192f

Browse files
committed
Merge olivierauverlot/login: combine local defaults with error_message and improved docs
2 parents cc95ae2 + 722dc74 commit 5a6192f

File tree

4 files changed

+39
-70
lines changed

4 files changed

+39
-70
lines changed

examples/official-site/examples/authentication/create_session_token.sql

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ delete from user_sessions where created_at < datetime('now', '-1 day');
44
-- check that the
55
SELECT 'authentication' AS component,
66
'login.sql?failed' AS link, -- redirect to the login page on error
7-
(SELECT password_hash FROM users WHERE username = :Username) AS password_hash, -- this is a hash of the password 'admin'
8-
:Password AS password; -- this is the password that the user sent through our form in 'index.sql'
7+
(SELECT password_hash FROM users WHERE username = :username) AS password_hash, -- this is a hash of the password 'admin'
8+
:password AS password; -- this is the password that the user sent through our form in 'index.sql'
99

1010
-- if we haven't been redirected, then the password is correct
1111
-- create a new session
12-
insert into user_sessions (session_token, username) values (sqlpage.random_string(32), :Username)
12+
insert into user_sessions (session_token, username) values (sqlpage.random_string(32), :username)
1313
returning 'cookie' as component, 'session_token' as name, session_token as value;
1414

1515
-- redirect to the authentication example home page

examples/official-site/examples/authentication/login.sql

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
select 'dynamic' as component, properties FROM example WHERE component = 'shell' LIMIT 1;
22

3-
select 'form' as component, 'Authentication' as title, 'Log in' as validate, 'create_session_token.sql' as action;
4-
select 'Username' as name, 'user' as prefix_icon, 'admin' as placeholder;
5-
select 'Password' as name, 'lock' as prefix_icon, 'admin' as placeholder, 'password' as type;
6-
7-
select 'alert' as component, 'danger' as color, 'Invalid username or password' as title where $failed is not null;
3+
select
4+
'login' as component,
5+
'create_session_token.sql' as action,
6+
'/assets/icon.webp' as image,
7+
'Demo Login Form' as title,
8+
'Username' as username,
9+
'Password' as password,
10+
case when $failed is not null then 'Invalid username or password. In this demo, you can log in with admin / admin.' end as error_message,
11+
'In this demo, the username is "admin" and the password is "admin".' as footer_md,
12+
'Sign in' as validate;
813

914
select 'text' as component, '
1015
1116
# Authentication
1217
1318
This is a simple example of an authentication form.
1419
It uses
15-
- the [`form`](/documentation.sql?component=form#component) component to create a login form
20+
- the [`login`](/documentation.sql?component=login#component) component to create a login form
1621
- the [`authentication`](/documentation.sql?component=authentication#component) component to check the user password
1722
- the [`cookie`](/documentation.sql?component=cookie#component) component to store a unique session token in the user browser
1823
- the [`redirect`](/documentation.sql?component=redirect#component) component to redirect the user to the login page if they are not logged in
Lines changed: 13 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
INSERT INTO component(name, icon, description, introduced_in_version) VALUES
22
('login', 'password-user', '
33
The login component is an authentication form with numerous customization options.
4-
The user enters their username and password,
5-
and is then redirected to another page, where you can use the [authentication](?component=authentication) component
6-
to check the credentials.
7-
4+
It offers the main functionalities for this type of form.
5+
The user can enter their username and password.
86
There are many optional attributes such as the use of icons on input fields, the insertion of a link to a page to reset the password, an option for the application to maintain the user''s identity via a cookie.
97
It is also possible to set the title of the form, display the company logo, or customize the appearance of the form submission button.
108
11-
This component does not implement any logic. It simply collects the username and password to pass them to the code responsible for authentication.
12-
It should be used in conjunction with other components such as [authentication](component.sql?component=authentication) and [cookie](component.sql?component=cookie) to actually allow or deny access.
9+
This component should be used in conjunction with other components such as [authentication](component.sql?component=authentication) and [cookie](component.sql?component=cookie).
10+
It does not implement any logic and simply collects the username and password to pass them to the code responsible for authentication.
1311
1412
A few things to know :
1513
- The form uses the POST method to transmit information to the destination page,
@@ -22,6 +20,7 @@ INSERT INTO parameter(component, name, description, type, top_level, optional) S
2220
('title','Title of the authentication form.','TEXT',TRUE,TRUE),
2321
('enctype','Form data encoding.','TEXT',TRUE,TRUE),
2422
('action','An optional link to a target page that will handle the results of the form. ','TEXT',TRUE,TRUE),
23+
('error_message','An error message to display above the form, typically shown after a failed login attempt.','TEXT',TRUE,TRUE),
2524
('username','Label and placeholder for the user account identifier text field.','TEXT',TRUE,FALSE),
2625
('password','Label and placeholder for the password field.','TEXT',TRUE,FALSE),
2726
('username_icon','Icon to display on the left side of the input field, on the same line.','ICON',TRUE,TRUE),
@@ -43,57 +42,10 @@ INSERT INTO parameter(component, name, description, type, top_level, optional) S
4342
INSERT INTO example(component, description, properties)
4443
VALUES (
4544
'login',
46-
'This example shows how to implement a complete custom login system in your SQLPage app.
47-
48-
### Database schema
49-
50-
`sqlpage/migrations/001_users.sql`
51-
52-
```sql
53-
create table account (
54-
username TEXT PRIMARY KEY,
55-
password_hash TEXT NOT NULL
56-
);
57-
58-
create table session (
59-
id TEXT PRIMARY KEY,
60-
username TEXT REFERENCES account(username)
61-
-- you could add more fields for session expiration, session metadata tracking...
62-
);
63-
```
64-
65-
### Process user credentials
66-
67-
Create a file named `login.sql`:
68-
69-
```sql
70-
SELECT ''authentication'' AS component,
71-
''/'' AS link, -- redirect the user to the homepage if the password is incorrect
72-
(SELECT password_hash FROM account WHERE username = :username) AS password_hash,
73-
:password AS password;
74-
75-
-- The code after this point is only executed if the user has sent the correct password
76-
77-
-- Generate a random session token
78-
INSERT INTO session (id, username)
79-
VALUES (sqlpage.random_string(32), :username)
80-
RETURNING ''cookie'' AS component, ''session_token'' AS name, id AS value,
81-
case when :remember is null then 3600*24*365 else 3600*4 end as max_age;
82-
83-
select ''redirect'' as component, ''protected.sql'' as link; -- once logged in, redirect to the protected page
84-
```
85-
86-
### Protect pages
87-
88-
Start all protected pages with
89-
90-
```sql
91-
select ''redirect'' as component, ''/'' as link where not exists (select 1 from session where id=sqlpage.cookie(''session_token''));
92-
```
93-
94-
### Login form on the home page
95-
',
96-
JSON('[{
45+
'Using the main options of the login component',
46+
JSON(
47+
'[
48+
{
9749
"component": "login",
9850
"action": "login.sql",
9951
"image": "../assets/icon.webp",
@@ -107,6 +59,8 @@ select ''redirect'' as component, ''/'' as link where not exists (select 1 from
10759
"remember_me_text": "Remember me",
10860
"footer_md": "Don''t have an account? [Register here](register.sql)",
10961
"validate": "Sign in"
110-
}]')
111-
),
62+
}
63+
]'
64+
)
65+
),
11266
('login', 'Most basic login form', JSON('[{"component": "login"}]'));

sqlpage/templates/login.handlebars

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,23 @@
1313
{{/if}}
1414
>
1515
{{#if image}}
16-
<div class="form-group d-flex justify-content-center align-items-center">
16+
<div class="form-group d-flex justify-content-center align-items-center mb-2">
1717
<img src="{{image}}"/>
1818
</div>
1919
{{/if}}
2020
{{#if title}}
2121
<h1 class="text-center mb-3">{{title}}</h1>
2222
{{/if}}
23+
{{#if error_message}}
24+
<div class="alert alert-danger mb-3" role="alert">
25+
<div class="alert-icon">
26+
{{icon_img 'alert-circle'}}
27+
</div>
28+
<div class="overflow-auto w-100">
29+
{{error_message}}
30+
</div>
31+
</div>
32+
{{/if}}
2333
<label class="form-label">{{username}}</label>
2434
<div class="input-icon mb-3">
2535
<span class="input-icon-addon">{{icon_img (default username_icon 'user-circle')}}</span>
@@ -31,7 +41,7 @@
3141
{{/if}}
3242
</label>
3343
<div class="input-icon mb-3">
34-
<span class="input-icon-addon">{{~icon_img (default password_icon 'key')~}}</span>
44+
<span class="input-icon-addon">{{~icon_img (default password_icon 'key')~}}</span>
3545
<input type="password" name="password" id="password" value="" class="form-control" placeholder="{{password}}" required="required" autocomplete="current-password" />
3646
</div>
3747
{{#if remember_me_text}}

0 commit comments

Comments
 (0)