diff options
Diffstat (limited to 'api/user.go')
-rw-r--r-- | api/user.go | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/api/user.go b/api/user.go new file mode 100644 index 0000000..4d4edba --- /dev/null +++ b/api/user.go | |||
@@ -0,0 +1,133 @@ | |||
1 | package api | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "regexp" | ||
6 | |||
7 | "github.com/gin-gonic/gin" | ||
8 | |||
9 | "immae.eu/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front/db" | ||
10 | ) | ||
11 | |||
12 | const ( | ||
13 | VALID_EMAIL_REGEX = `(?i)^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$` | ||
14 | ) | ||
15 | |||
16 | func IsValidEmailAddress(email string) bool { | ||
17 | r := regexp.MustCompile(VALID_EMAIL_REGEX) | ||
18 | |||
19 | return r.MatchString(email) | ||
20 | } | ||
21 | |||
22 | type SignParams struct { | ||
23 | Email string | ||
24 | Password string | ||
25 | } | ||
26 | |||
27 | type SignResult struct { | ||
28 | Token string `json:"token"` | ||
29 | } | ||
30 | |||
31 | func (s SignParams) Validate() *Error { | ||
32 | if !IsValidEmailAddress(s.Email) { | ||
33 | return &Error{InvalidEmail, "invalid email", fmt.Errorf("'%v' is not a valid email", s.Email)} | ||
34 | } | ||
35 | |||
36 | if s.Password == "" { | ||
37 | return &Error{InvalidPassword, "invalid password", fmt.Errorf("invalid password")} | ||
38 | } | ||
39 | |||
40 | return nil | ||
41 | } | ||
42 | |||
43 | type SignupQuery struct { | ||
44 | In SignParams | ||
45 | } | ||
46 | |||
47 | func (q SignupQuery) ValidateParams() *Error { | ||
48 | return q.In.Validate() | ||
49 | } | ||
50 | |||
51 | func (q SignupQuery) Run() (interface{}, *Error) { | ||
52 | user, err := db.GetUserByEmail(q.In.Email) | ||
53 | if err != nil { | ||
54 | return nil, NewInternalError(err) | ||
55 | } | ||
56 | |||
57 | if user != nil { | ||
58 | return nil, &Error{EmailExists, "email already taken", fmt.Errorf("'%v' is already registered '%v'", q.In.Email, user)} | ||
59 | } | ||
60 | |||
61 | newUser := db.User{Email: q.In.Email, Status: db.AwaitingConfirmation} | ||
62 | newUser.PasswordHash, err = db.HashPassword(q.In.Password) | ||
63 | if err != nil { | ||
64 | return nil, NewInternalError(err) | ||
65 | } | ||
66 | |||
67 | err = db.InsertUser(&newUser) | ||
68 | if err != nil { | ||
69 | return nil, NewInternalError(err) | ||
70 | } | ||
71 | |||
72 | token, err := CreateJwtToken(newUser.Id) | ||
73 | if err != nil { | ||
74 | return nil, NewInternalError(fmt.Errorf("cannot create jwt token %v", err)) | ||
75 | } | ||
76 | |||
77 | return SignResult{token}, nil | ||
78 | } | ||
79 | |||
80 | type SigninQuery struct { | ||
81 | In SignParams | ||
82 | } | ||
83 | |||
84 | func (q SigninQuery) ValidateParams() *Error { | ||
85 | return q.In.Validate() | ||
86 | } | ||
87 | |||
88 | func (q SigninQuery) Run() (interface{}, *Error) { | ||
89 | user, err := db.GetUserByEmail(q.In.Email) | ||
90 | if err != nil { | ||
91 | return nil, NewInternalError(err) | ||
92 | } | ||
93 | |||
94 | if user == nil { | ||
95 | return nil, &Error{InvalidCredentials, "invalid credentials", fmt.Errorf("no email '%v' found", q.In.Email)} | ||
96 | } | ||
97 | |||
98 | err = db.ValidatePassword(q.In.Password, user.PasswordHash) | ||
99 | if err != nil { | ||
100 | return nil, &Error{InvalidCredentials, "invalid credentials", err} | ||
101 | } | ||
102 | |||
103 | if user.Status != db.Confirmed { | ||
104 | return nil, &Error{UserNotConfirmed, "user awaiting admin validation", fmt.Errorf("user '%v' not confirmed", user)} | ||
105 | } | ||
106 | |||
107 | token, err := CreateJwtToken(user.Id) | ||
108 | if err != nil { | ||
109 | return nil, NewInternalError(err) | ||
110 | } | ||
111 | |||
112 | return SignResult{token}, nil | ||
113 | } | ||
114 | |||
115 | func UserConfirmed(c *gin.Context) *Error { | ||
116 | user, exists := c.Get("user") | ||
117 | |||
118 | if !exists { | ||
119 | return &Error{NotAuthorized, "not authorized", fmt.Errorf("no user key in context")} | ||
120 | } | ||
121 | |||
122 | if user.(db.User).Status != db.Confirmed { | ||
123 | return &Error{UserNotConfirmed, "user awaiting admin validation", fmt.Errorf("user '%v' not confirmed", user)} | ||
124 | } | ||
125 | |||
126 | return nil | ||
127 | } | ||
128 | |||
129 | func GetUser(c *gin.Context) db.User { | ||
130 | user, _ := c.Get("user") | ||
131 | |||
132 | return user.(db.User) | ||
133 | } | ||