Professional Documents
Culture Documents
────────────────────────────────────
MASTROMONACO Julien
RainbowBash
42 rue des Arcs-en-ciel
42000 Web Internet (near the mid’ clouds �)
Overview
The project is to build an API-REST distributing or receiving user data. This will be responsible
for managing users, different roles, access, and more.
All the basics functions that one could imagine will be made in order to be able to
accommodate changes quickly and cleanly. But, the maleability of the application will allow the
deactivation of lot of "components" without altering the health of the application.
Objectives
2. API Scalable
Links
● Trello (https://trello.com/b/sT3QTBc3/user-api)
● Github (https://github.com/JuMastro/user-api)
2
Technologies
Prod
Dev
More
● Docker
● Npm
● TravisCI (v2)
Requirements
Architecture
Requests workflow
4
Stories
Users
First stage
Second stage
Administrators
First stage
5
Second stage
Developers
First stage
Second stage
email regex(email)
Norms
Naming Conventions
Specs
Errors
If an error is detected there are two possible cases, first if the error is an expected error then
the route will return the error object with error code 400 (Bad request).In the second case, the
one where the error is not an expected error, the route will console.log the error and return an
error code 500 (Internal error).
Routes
Developers
Routes
Modules
V. Load balancer
4H
NO_REQUIREMENT
● Make express load-balancer app
● Make tests
WORKFLOW:
App instance
Select the laziest
server
REQUEST Load
App instance
Balancer
App instance
WORKFLOW:
Express app
MIDDLEWARES
REQUEST body- ...next RESPONSE
parser (routes)
Works with
request to get
friendly js/json
objects.
15
WORKFLOW:
Express app
MIDDLEWARES
REQUEST ...next RESPONSE
ip_access
(routes)
Check if client ip
is blocked.
WORKFLOW:
Express app
MIDDLEWARES
REQUEST user_acce ...next RESPONSE
ss (routes)
Check if client is
authenticated
and he’s
allowed
16
X. Abstract Controller
1H
NO_REQUIREMENT
● Find more information about the existence of translation module with node
● Make translation configuration
● Make translation module
● Make tests
Users
Modules
Routes
I. Registration
3-4 H
PUBLIC_KEY_GENERATOR, TOKEN_GENERATOR, EXTERNAL_ID_GENERATOR
DETAILS:
WORKFLOW:
24
db.userInfo.create({
last_user_ip: *UserIP*,
last_user_ip_date: Date(now),
registration_date: Date(now)
})
db.userProfile.create({
*EMPTY*
})
db.userArchive.create({
olds_usernames: [],
olds_emails: [],
olds_public_key: [],
user_id: *UserID*
})
db.userSecurity.create({
public_key: *generated*,
account_confirmation_token: *generated*,
account_confirmation_token_limit: Date(now+1H)
})
db.user.create({
identifiant_key: *generated*,
username: validate(*input*),
email: validate(*input*),
password: hash(validate(*input*)),
roles: [‘ROLE_USER’],
groups: [],
is_active: false,
is_blocked: false,
is_disabled: false,
is_confirmed: false,
user_security_id: *UserSecurityID*,
user_profile_id: *UserProfileID*,
user_info_id: *UserInfoID*
})
25
DETAILS:
WORKFLOW:
Clien API
t client.get (token)
Database update
db.userInfo.update({
registration_confirmation_date: Date(now)
})
db.user.update({
is_active: true,
is_confirmed: true
})
db.userSecurity.update({
account_confirmation_token: null,
account_confirmation_token_limit: null
})
26
2H
TOKEN_GENERATOR
● Create route configuration file and register it to app
● Create controller.action with WORKFLOW
● Create tests
DETAILS:
WORKFLOW:
Clien API
t client.post (email)
Database update
Send email
Return valid response (account confirmation)
db.userSecurity.update({
account_confirmation_token: *generated*,
account_confirmation_token_limit: Date(now + 1H)
})
27
IV. Login
3H
HASHER, JWT_ADAPTER
DETAILS:
WORKFLOW:
Clien API
t client.post (email | username, password)
Generate JsonWebToken
Database update
Return valid response (data: JWT)
db.userInfo.update({
last_conneted_date: Date(now)
})
28
V. Password forgot
3H
TOKEN_GENERATOR
● Create route configuration file and add it to app
● Create email template
● Create controller.action with WORKFLOW
● Create route tests
DETAILS:
WORKFLOW:
Clien API
t client.post (email)
Generate new
ERROR:
ResetPasswordToken
(Email not
found)
Update new token info in
database
Send email
Return valid response for each case (privacy) (Password recovery)
db.userSecurity.update({
reset_password_token: *generated*,
reset_password_token_limit: *generated*
})
29
DETAILS:
WORKFLOW:
Clien API
t client.post (email)
Database update
Send email
Valid response (Password updated)
db.user.update({
password: *hash(validate(input))*,
reset_password_token: null,
reset_password_token_limit: null
})
db.userInfo.update({
last_password_update: Date(now)
})
30
WORKFLOW:
Clien API
t client(Private: authUser).get
Database reading
Valid response
DETAILS:
DETAILS:
WORKFLOW:
Clien API
client.post (Private: authUser)
t ({ profileData })
Database update
Send email
Return valid response (Profile update)
db.userProfile.update({ *PROFILE_DATA* })
db.userInfos.update({
last_profile_update: Date(now)
})
32
DETAILS:
WORKFLOW:
Clien API
client.post (Private: authUser)
t (username)
Generate new
JsonWebToken
Send email
Return valid response (Username update)
db.user.update({
username: *validate(input)*
})
db.userArchive.update({
olds_username: exist.push(old_username)
})
db.userInfos.update({
last_username_update_date: Date(now)
33
})
X. Email update
3H
TOKEN_GENERATOR, HASHER
DETAILS:
WORKFLOW:
Clien API
client.post (Private: authUser)
t (email, password)
Generate confirmation
token
ERROR: Email already used
Database update
Send email
Return valid response (email update confirmation)
34
db.user.update({
email: *validate(input)*,
is_confirmed: false
})
db.userArchive.update({
olds_email: exists.push(old_email)
})
db.userInfos.update({
last_email_update: Date(now)
})
db.userSecurity.update({
update_email_token: *generated*,
update_email_token_limit: Date(now + 1H)
})
35
DETAILS:
WORKFLOW:
Clien API
t client.get (token)
Database update
db.user.update({
is_confirmed: true
})
db.userSecurity.update({
update_email_token: null,
update_email_token_limit: null
})
36
WORKFLOW:
Clien API
client.post
t (oldPassword, password,
passwordConfirmation)
Database update
Send email
Valid response (Password has been
updated)
DETAILS:
db.user.update({
password: *hash(validate(input))*
})
db.userInfo.update({
last_password_update: Date(now)
})
37
DETAILS:
DETAILS:
WORKFLOW:
Clien API
t client.get
Generate token
Database update
Send email
Valid response (New token created)
db.publicTokens.create({
secure_token: *generated*,
description: validate(input),
date: Date(now),
date_limit: Date(now + 120D),
user_id: *UserID*
})
39
DETAILS:
WORKFLOW:
Clien API
t client.get (token)
Send email
Valid response (Token deleted)
DETAILS:
WORKFLOW:
Clien API
t client.get ()
Generate token
Database update
Send email
Valid response (Disable account
confirmation)
db.userSecurity.update({
disable_account_token: *generated*,
disable_account_token_limit: Date(now)
})
41
DETAILS:
WORKFLOW:
Clien API
t client.get ()
Database update
Send email
Valid response (Disabled account)
db.user.update({
is_disabled: true
})
db.userSecurity.update({
disable_account_token: null,
disable_account_token_limit: null
})
42
43
DETAILS:
WORKFLOW:
Clien API
t client.get ()
Send email
ASYNC
(Dataset)
Build user dataset and send it to user
Parse many data
44
Administrators
Routes
I. Add roles
2H
NO_REQUIREMENT
● Create route configuration file and add it to app
● Create controller.action with WORKFLOW
● Create route tests
DETAILS:
WORKFLOW:
Clien API
t client.post (rolesList)
Database update
Valid response
db.user.update({
roles: exists.merge(input)
})
45
DETAILS:
WORKFLOW:
Clien API
t client.post (rolesList)
db.user.update({
roles: exists.remove(inputs)
})
46
DETAILS:
WORKFLOW:
Clien API
t client.get
Database request
Return response
47
DETAILS:
WORKFLOW:
Clien API
t client.post (dataSet)
Database update
Valid response
48
DETAILS:
WORKFLOW:
Clien API
t client.post (dataset list)
Database update
Valid response
49
DETAILS:
WORKFLOW:
Clien API
t client.get (page)
Database request
(select user using paginate)
Valid response
50
DETAILS:
WORKFLOW:
Clien API
client.post
t (username, email, password,
passwordConfirmation)
Hash password
db.userInfo.create({
last_user_ip: *UserIP*,
last_user_ip_date: Date(now),
registration_date: Date(now),
registration_confirmation_date: Date(now)
})
db.userProfile.create({
*EMPTY*
})
db.userArchive.create({
olds_usernames: [],
olds_emails: [],
user_id: *UserID*
})
db.userSecurity.create({
public_key: *generated*,
account_confirmation_token: null,
account_confirmation_token_limit: null
})
db.user.create({
identifiant_key: *generated*,
username: validate(*input*),
email: validate(*input*),
password: hash(validate(*input*)),
roles: [‘ROLE_USER’],
groups: [],
is_active: false,
is_blocked: false,
is_disabled: false,
is_confirmed: false,
user_security_id: *UserSecurityID*,
user_profile_id: *UserProfileID*,
user_info_id: *UserInfoID*
})
52
DETAILS:
WORKFLOW:
Clien API
t client.post (userList)
db.each.userInfo.update({
reason_disable: *input*
})
db.each.user.update({
is_disabled: true
})
53
DETAILS:
WORKFLOW:
Clien API
t client.post (userList)
db.each.user.delete( * CASCADE * )
54
DETAILS:
DETAILS:
WORKFLOW:
Clien API
t client.post (users, title, subject, content)
DETAILS:
WORKFLOW:
Clien API
t client.get (userId)
db.userSecurity.update({
public_key: *generated*
})
db.userArchive.update({
olds_public_key: exist.push(input)
})
57
DETAILS:
WORKFLOW:
Clien API
t client.get (userId)
db.userPublicTokens.create({
secure_token: *generated*,
description: *validate(input)*,
date: Date(now),
date_limit Date(now + 120D),
user_id: *UserID*
})
58
2H
NO_REQUIREMENT
DETAILS:
WORKFLOW:
Clien API
t client.get (tokenId)
db.userPublicTokens.create(WHERE id = :tokenId)
59
DETAILS:
WORKFLOW:
Clien API
t client.post (userId, time, reason)
Send email
Valid response (Banned user)
60
db.user.update({
is_active: false,
is_blocked: true
})
db.userSecurity.update({
blocked_account_date: Date(now),
blocked_account_limit: Date(now + input)
})
db.userInfo.update({
reason_blocked: validate(input)
})
61
XVI. Ban ip
2H
NO_REQUIREMENT
DETAILS:
WORKFLOW:
Clien API
t client.post (ip, type, reason, time)
Database update
Valid response
db.blockedIp.create({
ip: validate(input),
type: validate(input),
reason: validate(input),
date: Date(now),
date_limit: Date=(input)
})
62
DETAILS:
WORKFLOW:
Clien API
t client.get (PAGINATE)
Database read
Valid response
63
2H
NO_REQUIREMENT
DETAILS:
WORKFLOW:
Clien API
t client.get (PAGINATE)
Database read
Valid response
64
DETAILS:
WORKFLOW:
Clien API
t client.get (userId)
Send email
(User Dataset)
65
DETAILS:
WORKFLOW:
Clien API
t client.get (userId)
Send email
(User Anonymyzed
Dataset)
66
DETAILS:
WORKFLOW:
Clien API
t client.post (name, description)
db.group.create({
name: validate(input),
description: validate(input),
created_date: Date(now)
})
67
2H
NO_REQUIREMENT
DETAILS:
WORKFLOW:
Clien API
t client.get (groupId)
DETAILS:
WORKFLOW:
Clien API
t client.post (groupID, name, description)
db.group.update({
name: validate(input),
description: validate(input),
updated_date: Date(now)
})
69
DETAILS:
DETAILS:
WORKFLOW:
Clien API
t client.post (groupID, userID)
Database update
Valid response
db.usersGroups.create({
user_id: validate(input),
group_id: validate(input),
joinded_date: Date(now)
})
71
DETAILS:
WORKFLOW:
Clien API
t client.post (groupID, userID)
db.usersGroups.remove(
WHERE user_id = userId,
group_id = groupId
)
72
Module
8H
ADMINISTRATORS_ROUTES
● Create module
● Plug module to app
● Create module tests
The purpose of this module is to consume the parameters of the query of the route to see the
list of users. As the route is only accessible by admins, a large number of parameters can serve
as filters, starting with the global dates, roles, groups, username and more.