Skip to content

Commit cc95ae2

Browse files
committed
Improve login component documentation and usability
Add complete example with database schema, credential processing, and page protection. Update authentication migration to reference new login component. Enhance login template with default icons and autocomplete attributes. Make validate parameter optional with sensible default.
1 parent 3d7f780 commit cc95ae2

File tree

3 files changed

+71
-29
lines changed

3 files changed

+71
-29
lines changed

examples/official-site/sqlpage/migrations/07_authentication.sql

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ you have two main options:
1414
- does not require any external service
1515
- gives you fine-grained control over
1616
- which pages and actions are protected
17-
- the look of the login form
17+
- the look of the [login form](?component=login)
1818
- the duration of the session
1919
- the permissions of each user
2020
2. [**Single sign-on**](/sso)
@@ -128,12 +128,10 @@ Then, in all the pages that require authentication, you check if the cookie is p
128128
129129
You can check if the user has sent the correct password in a form, and if not, redirect them to a login page.
130130
131-
Create a login form in a file called `login.sql`:
131+
Create a login form in a file called `login.sql` that uses the [login component](?component=login):
132132
133133
```sql
134-
select ''form'' as component, ''Authentication'' as title, ''Log in'' as validate, ''create_session_token.sql'' as action;
135-
select ''Username'' as name, ''admin'' as placeholder;
136-
select ''Password'' as name, ''admin'' as placeholder, ''password'' as type;
134+
select ''login'' as component;
137135
```
138136
139137
And then, in `create_session_token.sql` :
Lines changed: 63 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
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-
It offers the main functionalities for this type of form.
5-
The user can enter their username and password.
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+
68
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.
79
It is also possible to set the title of the form, display the company logo, or customize the appearance of the form submission button.
810
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.
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.
1113
1214
A few things to know :
1315
- The form uses the POST method to transmit information to the destination page,
@@ -20,8 +22,8 @@ INSERT INTO parameter(component, name, description, type, top_level, optional) S
2022
('title','Title of the authentication form.','TEXT',TRUE,TRUE),
2123
('enctype','Form data encoding.','TEXT',TRUE,TRUE),
2224
('action','An optional link to a target page that will handle the results of the form. ','TEXT',TRUE,TRUE),
23-
('username','User account identifier.','TEXT',TRUE,FALSE),
24-
('password','User password.','TEXT',TRUE,FALSE),
25+
('username','Label and placeholder for the user account identifier text field.','TEXT',TRUE,FALSE),
26+
('password','Label and placeholder for the password field.','TEXT',TRUE,FALSE),
2527
('username_icon','Icon to display on the left side of the input field, on the same line.','ICON',TRUE,TRUE),
2628
('password_icon','Icon to display on the left side of the input field, on the same line.','ICON',TRUE,TRUE),
2729
('image','The URL of an centered image displayed before the title.','URL',TRUE,TRUE),
@@ -30,7 +32,7 @@ INSERT INTO parameter(component, name, description, type, top_level, optional) S
3032
('remember_me_text','A text for the option allowing the user to request the preservation of their identity. If the text is empty, the option is not displayed.','TEXT',TRUE,TRUE),
3133
('footer','A text placed at the bottom of the authentication form.','TEXT',TRUE,TRUE),
3234
('footer_md','A markdown text placed at the bottom of the authentication form. Useful for creating links to other pages (creating a new account, contacting technical support, etc.).','TEXT',TRUE,TRUE),
33-
('validate','The text to display in the button at the bottom of the form that submits the values.','TEXT',TRUE,FALSE),
35+
('validate','The text to display in the button at the bottom of the form that submits the values.','TEXT',TRUE,TRUE),
3436
('validate_color','The color of the button at the bottom of the form that submits the values. Omit this property to use the default color.','COLOR',TRUE,TRUE),
3537
('validate_shape','The shape of the validation button.','TEXT',TRUE,TRUE),
3638
('validate_outline','A color to outline the validation button.','COLOR',TRUE,TRUE),
@@ -41,10 +43,57 @@ INSERT INTO parameter(component, name, description, type, top_level, optional) S
4143
INSERT INTO example(component, description, properties)
4244
VALUES (
4345
'login',
44-
'Using the main options of the login component',
45-
JSON(
46-
'[
47-
{
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('[{
4897
"component": "login",
4998
"action": "login.sql",
5099
"image": "../assets/icon.webp",
@@ -58,7 +107,6 @@ VALUES (
58107
"remember_me_text": "Remember me",
59108
"footer_md": "Don''t have an account? [Register here](register.sql)",
60109
"validate": "Sign in"
61-
}
62-
]'
63-
)
64-
);
110+
}]')
111+
),
112+
('login', 'Most basic login form', JSON('[{"component": "login"}]'));

sqlpage/templates/login.handlebars

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,17 @@
2222
{{/if}}
2323
<label class="form-label">{{username}}</label>
2424
<div class="input-icon mb-3">
25-
{{#if username_icon}}
26-
<span class="input-icon-addon">{{icon_img username_icon}}</span>
27-
{{/if}}
28-
<input type="text" name="username" id="username" value="" class="form-control" placeholder="{{username}}" required="required" autofocus/>
25+
<span class="input-icon-addon">{{icon_img (default username_icon 'user-circle')}}</span>
26+
<input type="text" name="username" id="username" value="" class="form-control" placeholder="{{username}}" required="required" autofocus autocomplete="username"/>
2927
</div>
3028
<label class="form-label">{{password}}
3129
{{#if forgot_password_text}}
3230
<span class="form-label-description"><a href="{{forgot_password_link}}">{{forgot_password_text}}</a></span>
3331
{{/if}}
3432
</label>
3533
<div class="input-icon mb-3">
36-
{{#if password_icon}}
37-
<span class="input-icon-addon">{{~icon_img password_icon~}}</span>
38-
{{/if}}
39-
<input type="password" name="password" id="password" value="" class="form-control" placeholder="{{password}}" required="required"/>
34+
<span class="input-icon-addon">{{~icon_img (default password_icon 'key')~}}</span>
35+
<input type="password" name="password" id="password" value="" class="form-control" placeholder="{{password}}" required="required" autocomplete="current-password" />
4036
</div>
4137
{{#if remember_me_text}}
4238
<label class="form-check">
@@ -53,7 +49,7 @@
5349
{{#if validate_size}} btn-{{validate_size}} {{/if}}"
5450
type="submit"
5551
name="submit"
56-
value="{{validate}}"/>
52+
value="{{default validate 'Login'}}"/>
5753
</div>
5854
{{#if (or footer footer_md)}}
5955
<hr>

0 commit comments

Comments
 (0)