Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
Akamu
Game Server Go
Commits
c8e741d4
Commit
c8e741d4
authored
Oct 04, 2020
by
Julien Schröter
Committed by
Julien Schröter
Oct 20, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Create site to let user reset password without knowing the old one
parent
1468866a
Pipeline
#2052
passed with stage
in 8 minutes and 9 seconds
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
213 additions
and
0 deletions
+213
-0
assets/web/forgotPassword.tmpl
assets/web/forgotPassword.tmpl
+126
-0
endpoint/user/endpoint.go
endpoint/user/endpoint.go
+83
-0
setup/setup.go
setup/setup.go
+4
-0
No files found.
assets/web/forgotPassword.tmpl
0 → 100644
View file @
c8e741d4
<!DOCTYPE html>
<html
lang=
"en"
>
<head>
<meta
charset=
"UTF-8"
/>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
/>
<meta
http-equiv=
"X-UA-Compatible"
content=
"ie=edge"
/>
<title>
Akamu Account Password Reset
</title>
<style>
body
{
width
:
80%
;
margin
:
20px
auto
;
color
:
#555
;
}
body
,
form
input
{
font
:
18px
/
20px
-apple-system
,
BlinkMacSystemFont
,
Segoe
UI
,
Roboto
,
Helvetica
Neue
,
Arial
,
sans-serif
,
Apple
Color
Emoji
,
Segoe
UI
Emoji
,
Segoe
UI
Symbol
;
}
.error
{
color
:
#c00
;
}
.success
{
color
:
#0a0
;
}
input
[
type
=
"password"
]
{
margin
:
10px
0
;
padding
:
5px
2px
;
max-width
:
350px
;
width
:
100%
;
box-sizing
:
border-box
;
border
:
1px
solid
#ccc
;
}
input
[
type
=
"submit"
]
{
padding
:
7px
12px
;
background
:
#05d7d7
;
border
:
1px
solid
#ccc
;
border-radius
:
3px
;
font-weight
:
bold
;
color
:
#fff
;
text-shadow
:
0
0
1px
#026464
;
}
</style>
</head>
<body>
<img
src=
"https://akamu.de/img/logo.svg"
height=
"50px"
width=
"64px"
/>
<div
style=
"width: 100%; margin: 30px auto"
>
{{if .Done}}
<b
class=
"success"
>
Your password reset was successful.
</b>
<p>
You can log in with your new password in the App.
</p>
{{else if .Valid}}
<b>
Set a new password.
</b>
{{range $_, $e := .Errors}}
<p
class=
"error"
>
{{ $e }}
</p>
{{ end }}
<form
method=
"POST"
>
<p>
<label
for=
"password"
>
Password:
</label><br
/>
<input
type=
"password"
name=
"password"
id=
"password"
required
autofocus
/>
</p>
<p>
<label
for=
"confirm-password"
>
Confirm Password:
</label><br
/>
<input
type=
"password"
name=
"confirm-password"
id=
"confirm-password"
required
/>
</p>
<input
type=
"submit"
value=
"Reset Password"
/>
</form>
{{else if .ExpiredTime}}
<b
class=
"error"
>
Your link has expired.
</b>
<p>
Your link has expired since your request is older than 24h.
<br
/>
Just create a new request to reset your password.
</p>
{{else if .ExpiredUsed}}
<b
class=
"error"
>
You already updated your password.
</b>
<p>
Your link has expired since you already set a new password.
<br
/>
If you did not change your password since you requested a password
reset, please contact
<a
href=
"mailto:support@akamu.de"
>
support@akamu.de
</a>
.
</p>
{{else if .Failure}}
<b
class=
"error"
>
An error occurred.
</b>
<p>
Please try to reset your password again.
<br
/>
If it repeatedly failes, contact the support at
<a
href=
"mailto:support@akamu.de"
>
support@akamu.de
</a>
.
</p>
{{else}}
<b
class=
"error"
>
Your request seems to be invalid.
</b>
<p>
Check that you called the link as in your email.
<br
/>
Get additional help from
<a
href=
"mailto:support@akamu.de"
>
support@akamu.de
</a>
.
</p>
{{ end }}
</div>
</body>
</html>
endpoint/user/endpoint.go
View file @
c8e741d4
...
...
@@ -15,6 +15,7 @@ import (
"github.com/getsentry/raven-go"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"gitlab.akamu.de/akamu/game-server-go/schemas"
)
...
...
@@ -372,6 +373,88 @@ func ForgotPassword(repository UserQuery, tokenFactory otp.TokenFactory, templat
}
}
func
GetResetPassword
(
repository
UserQuery
,
tokenFactory
otp
.
TokenFactory
)
gin
.
HandlerFunc
{
return
func
(
ctx
*
gin
.
Context
)
{
token
,
ok
:=
ctx
.
GetQuery
(
"token"
)
if
!
ok
{
ctx
.
HTML
(
http
.
StatusBadRequest
,
"forgotPassword.tmpl"
,
nil
)
return
}
// Validate and get payload from token
userID
,
hash
,
err
:=
tokenFactory
.
ParsePasswordResetToken
(
token
)
if
err
==
otp
.
ErrTokenExpired
{
ctx
.
HTML
(
http
.
StatusGone
,
"forgotPassword.tmpl"
,
gin
.
H
{
"ExpiredTime"
:
true
})
return
}
else
if
err
!=
nil
{
ctx
.
HTML
(
http
.
StatusBadRequest
,
"forgotPassword.tmpl"
,
nil
)
return
}
// Check if user already updated the password
if
cred
,
err
:=
repository
.
SelectCredentialsByField
(
FieldID
,
userID
);
err
!=
nil
{
ctx
.
HTML
(
http
.
StatusInternalServerError
,
"forgotPassword.tmpl"
,
gin
.
H
{
"Failure"
:
true
})
return
}
else
if
cred
.
PasswordCipher
!=
hash
{
ctx
.
HTML
(
http
.
StatusGone
,
"forgotPassword.tmpl"
,
gin
.
H
{
"ExpiredUsed"
:
true
})
return
}
ctx
.
HTML
(
http
.
StatusOK
,
"forgotPassword.tmpl"
,
gin
.
H
{
"Valid"
:
true
})
}
}
func
PostResetPassword
(
repository
UserQuery
,
tokenFactory
otp
.
TokenFactory
)
gin
.
HandlerFunc
{
return
func
(
ctx
*
gin
.
Context
)
{
token
,
ok
:=
ctx
.
GetQuery
(
"token"
)
if
!
ok
{
ctx
.
HTML
(
http
.
StatusBadRequest
,
"forgotPassword.tmpl"
,
nil
)
return
}
userID
,
hash
,
err
:=
tokenFactory
.
ParsePasswordResetToken
(
token
)
if
err
==
otp
.
ErrTokenExpired
{
ctx
.
HTML
(
http
.
StatusGone
,
"forgotPassword.tmpl"
,
gin
.
H
{
"ExpiredTime"
:
true
})
return
}
else
if
err
!=
nil
{
ctx
.
HTML
(
http
.
StatusBadRequest
,
"forgotPassword.tmpl"
,
nil
)
return
}
var
formData
struct
{
Password
string
`form:"password" binding:"required,password"`
Confirm
string
`form:"confirm-password" binding:"required,eqfield=Password"`
}
if
err
:=
ctx
.
ShouldBind
(
&
formData
);
err
!=
nil
{
errs
:=
err
.
(
validator
.
ValidationErrors
)
ctx
.
HTML
(
http
.
StatusBadRequest
,
"forgotPassword.tmpl"
,
gin
.
H
{
"Valid"
:
true
,
"Errors"
:
errs
.
Translate
(
endpoint
.
GetTranslator
())})
return
}
// Check that the password has not been updated since creation of the token
if
cred
,
err
:=
repository
.
SelectCredentialsByField
(
FieldID
,
userID
);
err
!=
nil
{
raven
.
CaptureError
(
err
,
nil
)
ctx
.
HTML
(
http
.
StatusInternalServerError
,
"forgotPassword.tmpl"
,
gin
.
H
{
"Failure"
:
true
})
return
}
else
if
cred
.
PasswordCipher
!=
hash
{
ctx
.
HTML
(
http
.
StatusGone
,
"forgotPassword.tmpl"
,
gin
.
H
{
"ExpiredUsed"
:
true
})
return
}
// Update password
if
err
:=
repository
.
UpdatePassword
(
userID
,
formData
.
Password
);
err
!=
nil
{
raven
.
CaptureError
(
err
,
nil
)
ctx
.
HTML
(
http
.
StatusInternalServerError
,
"forgotPassword.tmpl"
,
gin
.
H
{
"Failure"
:
true
})
return
}
ctx
.
HTML
(
http
.
StatusOK
,
"forgotPassword.tmpl"
,
gin
.
H
{
"Done"
:
true
})
}
}
func
sendRegistrationVerification
(
tokenFactory
otp
.
TokenFactory
,
templatemail
*
sendmail
.
TemplateMail
,
userID
uint32
,
username
,
email
string
)
error
{
// Create token
token
,
err
:=
tokenFactory
.
CreateConfirmRegistrationToken
(
userID
,
email
)
...
...
setup/setup.go
View file @
c8e741d4
...
...
@@ -279,6 +279,10 @@ func SetupRoutes(courseRepository course.CourseQuery, flashcardRepository flashc
ctx
.
Header
(
"Allow"
,
"POST"
)
ctx
.
Status
(
200
)
})
router
.
GET
(
"/forgotpassword/reset"
,
user
.
GetResetPassword
(
userRepository
,
tokenFactory
))
router
.
POST
(
"/forgotpassword/reset"
,
user
.
PostResetPassword
(
userRepository
,
tokenFactory
))
router
.
PATCH
(
"/refreshjwt"
,
authMiddleware
.
RefreshHandler
)
router
.
OPTIONS
(
"/refreshjwt"
,
func
(
ctx
*
gin
.
Context
)
{
ctx
.
Header
(
"Allow"
,
"PATCH"
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment