Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
systemes-dinformation
project-template
SDK-GO
Commits
76edea90
Commit
76edea90
authored
Apr 10, 2020
by
Alexis POYEN
Browse files
Technical : save user in DB instead of file
parent
86e3d068
Pipeline
#4848
failed with stages
in 3 minutes and 22 seconds
Changes
8
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
configs/users.json
deleted
100644 → 0
View file @
86e3d068
[
{
"id"
:
1
,
"idOAuth"
:
""
,
"login"
:
"Dupond"
,
"role"
:
"CLIENT"
,
"passwordHash"
:
"$2a$10$PgiAoLxZhgNtr7kRK/DH5ezwT./7vRkWqFNEtJD1670z3Zf60HqgG"
},
{
"id"
:
2
,
"idOAuth"
:
""
,
"login"
:
"Bakery"
,
"role"
:
"CLIENT"
,
"passwordHash"
:
"$2a$10$PgiAoLxZhgNtr7kRK/DH5ezwT./7vRkWqFNEtJD1670z3Zf60HqgG"
},
{
"id"
:
3
,
"idOAuth"
:
""
,
"login"
:
"banker"
,
"role"
:
"BANKER"
,
"passwordHash"
:
"$2a$10$w6aIsC8lfMSB9tXIDRgk9OztQS.4gBQA9Uoi0X7mCzz5mlTRIx4tq"
},
{
"id"
:
4
,
"idOAuth"
:
""
,
"login"
:
"admin"
,
"role"
:
"ADMIN"
,
"passwordHash"
:
"$2a$10$PgiAoLxZhgNtr7kRK/DH5ezwT./7vRkWqFNEtJD1670z3Zf60HqgG"
},
{
"id"
:
5
,
"idOAuth"
:
"1"
,
"login"
:
"ADMIN"
,
"displayName"
:
"Ad MIN"
,
"role"
:
"ADMIN"
},
{
"id"
:
6
,
"idOAuth"
:
""
,
"login"
:
"banker2"
,
"role"
:
"BANKER"
,
"passwordHash"
:
"$2a$10$w6aIsC8lfMSB9tXIDRgk9OztQS.4gBQA9Uoi0X7mCzz5mlTRIx4tq"
}
]
\ No newline at end of file
data/users.db
0 → 100644
View file @
76edea90
File added
internal/models/models.go
View file @
76edea90
...
...
@@ -12,8 +12,6 @@ import (
_
"github.com/jinzhu/gorm/dialects/sqlite"
)
type
authzFunc
func
(
http
.
Handler
,
[]
string
,
bool
)
http
.
Handler
// DataHandler init a gorm DB an presents API handlers
type
DataHandler
struct
{
db
*
gorm
.
DB
...
...
internal/rootmux/rootmux_test.go
View file @
76edea90
...
...
@@ -33,8 +33,7 @@ func init() {
func
TestAll
(
t
*
testing
.
T
)
{
os
.
Mkdir
(
"data"
,
os
.
ModePerm
)
os
.
Create
(
"./data/test.db"
)
// Set the users file
auth
.
UsersFile
=
"../../configs/users.json"
os
.
Link
(
"../../data/users.db"
,
"./data/users.db"
)
// Create the mock OAuth2 server
oAuth2Server
:=
httptest
.
NewServer
(
mocks
.
CreateMockOAuth2
())
defer
oAuth2Server
.
Close
()
...
...
@@ -124,6 +123,7 @@ func resetData(t *testing.T) {
os
.
RemoveAll
(
"./data"
)
os
.
Mkdir
(
"data"
,
os
.
ModePerm
)
os
.
Create
(
"./data/test.db"
)
os
.
Link
(
"../../data/users.db"
,
"./data/users.db"
)
ts
,
do
,
_
:=
createTester
(
t
)
defer
ts
.
Close
()
// Close the tester
...
...
@@ -134,6 +134,7 @@ func resetData(t *testing.T) {
token
:=
auth
.
TokenData
{}
json
.
Unmarshal
([]
byte
(
response
),
&
token
)
xsrfHeader
:=
tester
.
Header
{
Key
:
"XSRF-TOKEN"
,
Value
:
token
.
XSRFToken
}
// Create one banker
do
(
"POST"
,
"/api/UserBankers"
,
xsrfHeader
,
`{"UserID":3,"Name":"Banker"}`
,
200
,
""
)
// Create an other banker
...
...
pkg/auth/auth_test.go
View file @
76edea90
package
auth
import
(
"encoding/json"
"io/ioutil"
"net/http"
"os"
"reflect"
"testing"
...
...
@@ -39,18 +36,7 @@ func TestCheckUserHasRole(t *testing.T) {
}
}
func
TestAddUser
(
t
*
testing
.
T
)
{
UsersFile
=
writeUsers
()
defer
os
.
Remove
(
UsersFile
)
handler
:=
http
.
HandlerFunc
(
AddUser
)
tester
.
DoRequestOnHandler
(
t
,
handler
,
"POST"
,
"/"
,
noH
,
`{"login":"adminTest","password": "password","role":"ADMINS"}`
,
http
.
StatusOK
,
`[{"id":1,"idOAuth":"","login":"admin"`
)
tester
.
DoRequestOnHandler
(
t
,
handler
,
"POST"
,
"/"
,
noH
,
`{"login":"admin","password": ""}`
,
http
.
StatusBadRequest
,
`passwords cannot be blank`
)
}
func
TestMatchUser
(
t
*
testing
.
T
)
{
UsersFile
=
"../../configs/users.json"
existingUser
:=
User
{
ID
:
2
,
Login
:
"Bakery"
,
Role
:
"CLIENT"
,
PasswordHash
:
"$2a$10$PgiAoLxZhgNtr7kRK/DH5ezwT./7vRkWqFNEtJD1670z3Zf60HqgG"
}
veryLongString
,
_
:=
common
.
GenerateRandomString
(
10000
)
specialCharString
:=
"
\"
"
...
...
@@ -78,9 +64,11 @@ func TestMatchUser(t *testing.T) {
{
"special_char_string_as_password"
,
args
{
User
{
Login
:
"Bakery"
,
Password
:
specialCharString
}},
User
{},
true
},
{
"special_char_string_as_user_and_password"
,
args
{
User
{
Login
:
specialCharString
,
Password
:
specialCharString
}},
User
{},
true
},
}
os
.
Mkdir
(
"data"
,
os
.
ModePerm
)
os
.
Link
(
"../../data/users.db"
,
"./data/users.db"
)
for
_
,
tt
:=
range
tests
{
t
.
Run
(
tt
.
name
,
func
(
t
*
testing
.
T
)
{
got
,
err
:=
MatchUser
(
tt
.
args
.
sentUser
)
got
,
err
:=
NewDataHandler
()
.
MatchUser
(
tt
.
args
.
sentUser
)
if
(
err
!=
nil
)
!=
tt
.
wantErr
{
t
.
Errorf
(
"MatchUser() error = %v, wantErr %v"
,
err
,
tt
.
wantErr
)
return
...
...
@@ -91,20 +79,3 @@ func TestMatchUser(t *testing.T) {
})
}
}
func
writeUsers
()
(
name
string
)
{
users
:=
[]
*
User
{
{
ID
:
1
,
Login
:
"admin"
,
Password
:
"password"
},
{
ID
:
2
,
Login
:
"user"
,
Password
:
"password"
},
}
f
,
err
:=
ioutil
.
TempFile
(
""
,
"users"
)
if
err
!=
nil
{
panic
(
err
)
}
defer
f
.
Close
()
err
=
json
.
NewEncoder
(
f
)
.
Encode
(
users
)
if
err
!=
nil
{
panic
(
err
)
}
return
f
.
Name
()
}
pkg/auth/dbusers.go
0 → 100644
View file @
76edea90
package
auth
import
(
"errors"
"github.com/jinzhu/gorm"
)
// DataHandler has the db connection
type
DataHandler
struct
{
db
*
gorm
.
DB
}
// NewDataHandler init a DataHandler and returns a pointer to it
func
NewDataHandler
()
*
DataHandler
{
db
,
err
:=
gorm
.
Open
(
"sqlite3"
,
"./data/users.db"
)
if
err
!=
nil
{
panic
(
"failed to connect database"
)
}
db
.
LogMode
(
true
)
// Migrate the schema
db
.
AutoMigrate
(
&
User
{})
return
&
DataHandler
{
db
:
db
}
}
func
(
d
*
DataHandler
)
saveUser
(
user
User
)
error
{
d
.
db
.
Create
(
&
user
)
return
nil
}
func
(
d
*
DataHandler
)
getUsers
()
[]
User
{
var
users
[]
User
d
.
db
.
Find
(
&
users
)
return
users
}
func
(
d
*
DataHandler
)
removeUser
(
id
int
)
error
{
var
o
User
if
err
:=
d
.
db
.
First
(
&
o
,
id
)
.
Error
;
err
!=
nil
{
return
errors
.
New
(
"id does not exist"
)
}
d
.
db
.
Delete
(
&
o
)
return
nil
}
pkg/auth/inmemory.go
View file @
76edea90
...
...
@@ -4,7 +4,6 @@ import (
"encoding/json"
"errors"
"net/http"
"sort"
"strconv"
"strings"
"time"
...
...
@@ -33,7 +32,8 @@ func (m Manager) HandleInMemoryLogin(w http.ResponseWriter, r *http.Request) {
return
}
// Try to match the user with an user in the database
user
,
err
:=
MatchUser
(
sentUser
)
d
:=
NewDataHandler
()
user
,
err
:=
d
.
MatchUser
(
sentUser
)
if
err
!=
nil
{
http
.
Error
(
w
,
err
.
Error
(),
403
)
log
.
Logger
.
Printf
(
"| %v | Login failure | %v | %v"
,
sentUser
.
Login
,
r
.
RemoteAddr
,
log
.
GetCityAndCountryFromRequest
(
r
))
...
...
@@ -62,43 +62,34 @@ func (a ByID) Less(i, j int) bool { return a[i].ID < a[j].ID }
// ProcessUsers processes users regarding of HTTP method
func
ProcessUsers
(
w
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
d
:=
NewDataHandler
()
switch
method
:=
req
.
Method
;
method
{
case
"GET"
:
SendUsers
(
w
,
req
)
d
.
SendUsers
(
w
,
req
)
case
"POST"
:
AddUser
(
w
,
req
)
d
.
AddUser
(
w
,
req
)
case
"DELETE"
:
DeleteUser
(
w
,
req
)
d
.
DeleteUser
(
w
,
req
)
default
:
http
.
Error
(
w
,
"method not allowed"
,
400
)
}
}
// SendUsers send users as response from an http requests
func
SendUsers
(
w
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
var
users
[]
User
err
:=
common
.
Load
(
UsersFile
,
&
users
)
if
err
!=
nil
{
http
.
Error
(
w
,
err
.
Error
(),
400
)
return
}
func
(
d
*
DataHandler
)
SendUsers
(
w
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
var
users
=
d
.
getUsers
()
json
.
NewEncoder
(
w
)
.
Encode
(
users
)
}
// AddUser adds an user
func
AddUser
(
w
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
var
users
[]
User
err
:=
common
.
Load
(
UsersFile
,
&
users
)
if
err
!=
nil
{
http
.
Error
(
w
,
err
.
Error
(),
400
)
return
}
func
(
d
*
DataHandler
)
AddUser
(
w
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
var
users
=
d
.
getUsers
()
if
req
.
Body
==
nil
{
http
.
Error
(
w
,
"please send a request body"
,
400
)
return
}
var
newUser
User
err
=
json
.
NewDecoder
(
req
.
Body
)
.
Decode
(
&
newUser
)
err
:
=
json
.
NewDecoder
(
req
.
Body
)
.
Decode
(
&
newUser
)
if
_
,
ok
:=
err
.
(
*
json
.
UnmarshalTypeError
);
!
ok
&&
err
!=
nil
{
http
.
Error
(
w
,
err
.
Error
(),
400
)
return
...
...
@@ -128,54 +119,30 @@ func AddUser(w http.ResponseWriter, req *http.Request) {
return
}
}
// Sauvegarder l'utilisateur dans InMemory
users
=
append
(
users
,
newUser
)
sort
.
Sort
(
ByID
(
users
))
err
=
common
.
Save
(
UsersFile
,
&
users
)
if
err
!=
nil
{
http
.
Error
(
w
,
err
.
Error
(),
400
)
return
}
SendUsers
(
w
,
req
)
d
.
saveUser
(
newUser
)
d
.
SendUsers
(
w
,
req
)
}
// DeleteUser adds an user
func
DeleteUser
(
w
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
var
users
[]
User
err
:=
common
.
Load
(
UsersFile
,
&
users
)
if
err
!=
nil
{
http
.
Error
(
w
,
err
.
Error
(),
400
)
return
}
func
(
d
*
DataHandler
)
DeleteUser
(
w
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
pathElements
:=
strings
.
Split
(
req
.
URL
.
Path
,
"/"
)
idx
,
err
:=
strconv
.
Atoi
(
pathElements
[
len
(
pathElements
)
-
1
])
if
err
!=
nil
{
http
.
Error
(
w
,
"please provide an user index"
,
400
)
return
}
// Add the user only if the name doesn't exists yet
newUsers
:=
users
[
:
0
]
for
_
,
user
:=
range
users
{
if
err
==
nil
&&
user
.
ID
!=
idx
{
newUsers
=
append
(
newUsers
,
user
)
}
}
err
=
common
.
Save
(
UsersFile
,
&
newUsers
)
err
=
d
.
removeUser
(
idx
)
if
err
!=
nil
{
http
.
Error
(
w
,
err
.
Error
(),
400
)
return
}
SendUsers
(
w
,
req
)
d
.
SendUsers
(
w
,
req
)
}
// MatchUser attempt to find the given user against users in configuration file
func
MatchUser
(
sentUser
User
)
(
User
,
error
)
{
func
(
d
*
DataHandler
)
MatchUser
(
sentUser
User
)
(
User
,
error
)
{
var
emptyUser
User
var
users
[]
User
err
:=
common
.
Load
(
UsersFile
,
&
users
)
if
err
!=
nil
{
return
emptyUser
,
err
}
var
users
=
d
.
getUsers
()
for
_
,
user
:=
range
users
{
if
user
.
Login
==
sentUser
.
Login
{
notFound
:=
bcrypt
.
CompareHashAndPassword
([]
byte
(
user
.
PasswordHash
),
[]
byte
(
sentUser
.
Password
))
...
...
pkg/auth/oauth2.go
View file @
76edea90
...
...
@@ -6,7 +6,6 @@ import (
"fmt"
"net/http"
"os"
"sort"
"strings"
"time"
...
...
@@ -126,7 +125,8 @@ func (m Manager) HandleOAuth2Callback() http.Handler {
userOauth2
.
Groups
[
key
]
=
strings
.
TrimPrefix
(
strings
.
Split
(
role
,
","
)[
0
],
"CN="
)
}
// Store the user in cookie
user
,
err
:=
getUserInMemory
(
userOauth2
)
dh
:=
NewDataHandler
()
user
,
err
:=
dh
.
getUserInMemory
(
userOauth2
)
if
err
!=
nil
{
http
.
Error
(
w
,
err
.
Error
(),
400
)
return
...
...
@@ -147,22 +147,17 @@ func (m Manager) HandleOAuth2Callback() http.Handler {
return
http
.
HandlerFunc
(
oauth2Handler
)
}
func
getUserInMemory
(
userOAuth2
UserOAuth2
)
(
User
,
error
)
{
var
user
User
var
users
[]
User
err
:=
common
.
Load
(
UsersFile
,
&
users
)
if
err
!=
nil
{
return
user
,
errors
.
New
(
"Error on loading user"
)
}
func
(
d
*
DataHandler
)
getUserInMemory
(
userOAuth2
UserOAuth2
)
(
User
,
error
)
{
var
users
=
d
.
getUsers
()
for
_
,
val
:=
range
users
{
if
userOAuth2
.
ID
==
val
.
IDOAuth
{
return
val
,
nil
}
}
return
addUserInMemory
(
userOAuth2
)
return
d
.
addUserInMemory
(
userOAuth2
)
}
func
addUserInMemory
(
userOauth2
UserOAuth2
)
(
User
,
error
)
{
func
(
d
*
DataHandler
)
addUserInMemory
(
userOauth2
UserOAuth2
)
(
User
,
error
)
{
var
user
User
// Define user role or refuse if not in a correct group
for
_
,
userRole
:=
range
userOauth2
.
Groups
{
...
...
@@ -193,11 +188,6 @@ func addUserInMemory(userOauth2 UserOAuth2) (User, error) {
}
}
// Sauvegarder l'utilisateur dans InMemory
users
=
append
(
users
,
user
)
sort
.
Sort
(
ByID
(
users
))
err
=
common
.
Save
(
UsersFile
,
&
users
)
if
err
!=
nil
{
return
user
,
errors
.
New
(
"Error on saving user"
)
}
d
.
saveUser
(
user
)
return
user
,
nil
}
Write
Preview
Supports
Markdown
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