Task 2 — User Login and Access Control
Objective
Create a small user-access system.
The implementation must support:
- user storage
- user validation
- authentication
- password expiration
- regular and streaming login modes
- sector authorization
- request authorization
- IP-address authorization
- failed-login tracking
- automatic suspension
The validation system created in Task 1 must be used when new users are added.
User Model
Create a User structure containing:
Name
ID
Username
Password
PasswordValidUntil
PhoneNumber
Team
RegularLoginAllowed
StreamingLoginAllowed
AllowedSectors
AllowedRequests
AllowedIPAddresses
FailedLoginAttempts
Suspended
A possible Go representation is:
type User struct {
Name string
ID string
Username string
Password string
PasswordValidUntil time.Time
PhoneNumber string
Team string
RegularLoginAllowed bool
StreamingLoginAllowed bool
AllowedSectors []int
AllowedRequests []int
AllowedIPAddresses []string
FailedLoginAttempts int
Suspended bool
}
The exact field types may be adapted to the implementation.
Sector Request IDs
The system contains four sectors.
Sector 1
[]int{
1, 2, 3,
10, 11, 12, 13,
20, 21, 22,
30, 35,
45, 46,
50,
}
Sector 2
[]int{
100, 101, 102, 103, 104, 105, 106,
110, 111, 112, 113,
115, 116, 117,
120,
}
Sector 3
[]int{
200, 202, 204, 206, 208,
210, 212, 214, 216,
220, 240,
}
Sector 4
[]int{
302, 304, 306, 308,
320, 325,
350, 360, 370, 390, 399,
}
Allowed Sectors
A user may be configured for:
all
1
2
3
4
A typed representation is preferred over mixing strings and integers.
For example, an implementation may use:
type SectorAccess struct {
All bool
Sectors []int
}
User Store
Create a custom user store containing three users.
You may choose the actual attribute values.
For example:
type UserStore struct {
Users []User
}
When a new user is added:
- validate all required string attributes using Task 1
- validate the sector configuration
- validate request IDs
- validate allowed IP addresses
- validate password-expiration data
- reject the user when validation fails
LoginData
Create a structure named:
LoginData
with the following attributes:
LoginType
ReqID
Username
UserPass
AllowedAddress
For example:
type LoginData struct {
LoginType string
ReqID int
Username string
UserPass string
AllowedAddress string
}
Login Types
The user model distinguishes:
regular login
streaming login
A typed representation is recommended.
For example:
type LoginType string
const (
LoginTypeRegular LoginType = "regular"
LoginTypeStreaming LoginType = "streaming"
)
Login Processing
Create a function that receives:
LoginData
and verifies the login attempt against the user store.
Conceptually:
CheckLogin(store, loginData)
Login Validation Order
A login attempt should verify relevant conditions such as:
- user exists
- user is not suspended
- password is correct
- password has not expired
- requested login type is allowed
- source IP address is allowed
- request ID is allowed
- the request belongs to an allowed sector
All applicable authorization rules must be satisfied.
Successful Login
On successful login, return information containing:
Name
Username
Team
AllowedSectors
AllowedRequests
A structured result can be used:
type LoginSuccess struct {
Name string
Username string
Team string
AllowedSectors []int
AllowedRequests []int
}
Failed Login
A failed login must return a list of errors.
For example:
type LoginError struct {
Code string
Message string
}
The result may contain:
[]LoginError
rather than only one error.
Required Failure Scenarios
Create examples for the following failures.
Bad Username or Password
The submitted credentials do not match a valid user.
Expired Password
The current UTC time is later than:
PasswordValidUntil
Request ID Not Allowed
The requested:
ReqID
is not included in the user’s allowed request IDs.
IP Address Not Allowed
The submitted address is not contained in:
AllowedIPAddresses
Streaming Login Not Allowed
A streaming login was requested but:
StreamingLoginAllowed == false
Suspended User
The account is already suspended.
Failed Login Counter
Every failed login attempt must update:
FailedLoginAttempts
according to the suspension rule.
The original task states:
USER is suspended on second failed login attempt.
Therefore, once the failed-login count reaches:
2
set:
Suspended = true
Suspension Rule
Conceptually:
first failed login
↓
FailedLoginAttempts = 1
Suspended = false
second failed login
↓
FailedLoginAttempts = 2
Suspended = true
Further login attempts must fail because the user is suspended.
Important Security Behavior
A failed login caused by an unknown username cannot update the state of a user that does not exist.
For an existing username with invalid authentication or authorization data, the implementation must define which failure types increment the failed-login counter.
The original task does not distinguish authentication failures from authorization failures for this purpose.
Therefore, the implementation must document its chosen policy.
One reasonable interpretation is:
credential failures increment FailedLoginAttempts
authorization failures return errors without incrementing credential-failure state
but this behavior is an implementation decision beyond what the original source explicitly specifies.
Successful Login and Counter Reset
The original task does not state whether a successful login resets:
FailedLoginAttempts
Do not silently assume a reset rule.
If the implementation adds one, document it explicitly.
Request-to-Sector Relationship
A request ID belongs to one of the four defined sectors.
A login request should satisfy both:
the user is allowed to access the request ID
and:
the user is allowed to access the sector containing that request ID
Validation Integration
When users are created, use Task 1 to validate attributes such as:
- Name
- ID
- Username
- Password
- PasswordValidUntil
- PhoneNumber
- AllowedIPAddresses
The appropriate validation type should be selected for each field.
Testing
Create at least:
- one successful login
- bad username or password
- expired password
- unauthorized request ID
- unauthorized IP address
- forbidden streaming login
- suspended-user login
- first failed login
- second failed login causing suspension
Implementation Notes
Keep the responsibilities separated.
A useful design is:
User validation
↓
User store
↓
Authentication
↓
Authorization
↓
Account-state update
↓
Structured response
Avoid implementing every rule inside one large conditional block.