Commit 49005bf2 authored by Tristan Claverie's avatar Tristan Claverie Committed by Loïck Bonniot

[dfssp] Add mongo entities for mongo and tests

parent 914e6902
Pipeline #211 passed with stage
...@@ -24,6 +24,8 @@ Unit tests: ...@@ -24,6 +24,8 @@ Unit tests:
- "go test -coverprofile mails.part -v dfss/mails" - "go test -coverprofile mails.part -v dfss/mails"
- "go test -coverprofile net.part -v dfss/net" - "go test -coverprofile net.part -v dfss/net"
- "go test -coverprofile authority.part -v dfss/dfssp/authority" - "go test -coverprofile authority.part -v dfss/dfssp/authority"
- "go test -coverprofile dfssp_user.part -v dfss/dfssp/user"
- "go test -coverprofile dfssp_contract.part -v dfss/dfssp/contract"
- "echo 'mode: set' *part > c.out" - "echo 'mode: set' *part > c.out"
- "grep -h -v 'mode: set' *part >> c.out" - "grep -h -v 'mode: set' *part >> c.out"
- "go tool cover -html=c.out -o coverage.html" - "go tool cover -html=c.out -o coverage.html"
...@@ -39,6 +41,8 @@ ARM tests: ...@@ -39,6 +41,8 @@ ARM tests:
- "go test -cover -short -v dfss/mgdb" - "go test -cover -short -v dfss/mgdb"
- "go test -cover -short -v dfss/net" - "go test -cover -short -v dfss/net"
- "go test -cover -short -v dfss/dfssp/authority" - "go test -cover -short -v dfss/dfssp/authority"
- "go test -cover -short -v dfss/dfssp/user"
- "go test -cover -short -v dfss/dfssp/contract"
Code lint: Code lint:
stage: test stage: test
......
package contract
import (
"dfss/mgdb"
"time"
"gopkg.in/mgo.v2/bson"
)
// File : Represents a file structure
type File struct {
Name string `key:"name" bson:"name"` // Name of the File
Hash string `key:"hash" bson:"hash"` // Hash of the File
Hosted bool `key:"hosted" bson:"hosted"` // True if hosted on the platform, else false
}
// Signer : Informations about the signer of a contract
type Signer struct {
UserID bson.ObjectId `key:"userId" bson:"userId"`
Email string `key:"email" bson:"email"`
Hash string `key:"hash" bson:"hash"`
}
// NewSigner : Creates a signer associated to a contract
func NewSigner() *Signer {
return &Signer{
UserID: bson.NewObjectId(),
}
}
// Contract : Informations about a contract to be signed
type Contract struct {
ID bson.ObjectId `key:"_id" bson:"_id"`
Date time.Time `key:"date" bson:"date"`
Comment string `key:"comment" bson:"comment"`
Ready bool `key:"ready" bson:"ready"`
File *File `key:"file" bson:"file"`
Signers []Signer `key:"signers" bson:"signers"`
}
// NewContract : Creates a new contract
func NewContract() *Contract {
file := File{}
var signers []Signer
return &Contract{
ID: bson.NewObjectId(),
Date: time.Now(),
File: &file,
Signers: signers,
}
}
// AddSigner : Add a signer to the contract
func (c *Contract) AddSigner(email, hash string) {
signer := NewSigner()
signer.Email = email
signer.Hash = hash
c.Signers = append(c.Signers, *signer)
}
// Repository to contains every complex methods related to contract
type Repository struct {
Collection *mgdb.MongoCollection
}
// NewRepository : Creates a new Contract Repository
func NewRepository(collection *mgdb.MongoCollection) *Repository {
return &Repository{
collection,
}
}
package contract
import (
"dfss/mgdb"
"fmt"
"os"
"testing"
)
var err error
var collection *mgdb.MongoCollection
var manager *mgdb.MongoManager
var dbURI string
var repository *Repository
func TestMain(m *testing.M) {
dbURI = os.Getenv("DFSS_MONGO_URI")
if dbURI == "" {
dbURI = "mongodb://localhost/dfss"
}
manager, err = mgdb.NewManager(dbURI)
collection = manager.Get("demo")
repository = NewRepository(collection)
// Run
code := m.Run()
// Teardown
// The collection is created automatically on
// first connection, that's why we do not recreate it manually
err = collection.Drop()
if err != nil {
fmt.Println("An error occurred while droping the collection")
}
manager.Close()
os.Exit(code)
}
func TestAddSigner(t *testing.T) {
contract := NewContract()
contract.AddSigner("mail1", "hash1")
contract.AddSigner("mail2", "hash2")
signers := contract.Signers
var fixedSigners [2]Signer
copy(fixedSigners[:], signers[:2])
if len(signers) != 2 {
t.Fatal("Signers are not inserted correctly")
}
helperCompareEmailAndHash(t, fixedSigners)
}
func helperCompareFiles(t *testing.T, contract, fetched Contract) {
if contract.File.Name != fetched.File.Name || contract.File.Hash != fetched.File.Hash || contract.File.Hosted != fetched.File.Hosted {
t.Fatal("Contract files doesn't match")
}
}
func helperCompareEmailAndHash(t *testing.T, signers [2]Signer) {
if signers[0].Email != "mail1" && signers[0].Email != "mail2" || signers[1].Email != "mail1" && signers[1].Email != "mail2" {
t.Fatal("Signers are not correctly added")
}
if signers[0].Hash != "hash1" && signers[0].Hash != "hash2" || signers[1].Hash != "hash1" && signers[1].Hash != "hash2" {
t.Fatal("Signers are not correctly added")
}
}
func helperCompareInformations(t *testing.T, contract, fetched Contract) {
if contract.Date.Unix() != fetched.Date.Unix() || contract.Comment != fetched.Comment || contract.Ready != fetched.Ready || len(contract.Signers) != len(fetched.Signers) {
t.Fatal("Contract informations doesn't match")
}
}
// Insert a contract with 2 users and check the fields are correctly persisted
func TestInsertContract(t *testing.T) {
contract := NewContract()
contract.AddSigner("mail1", "hash1")
contract.AddSigner("mail1", "hash1")
contract.File.Name = "file"
contract.File.Hash = "hashFile"
contract.File.Hosted = false
contract.Comment = "comment"
contract.Ready = true
_, err := repository.Collection.Insert(contract)
if err != nil {
t.Fatal("Contract not inserted successfully in the database")
}
fmt.Println("Successfully persisted contract")
fetched := Contract{}
selector := Contract{
ID: contract.ID,
}
err = repository.Collection.FindByID(selector, &fetched)
if err != nil {
t.Fatal("Contract could not be successfully retrieved")
}
helperCompareFiles(t, *contract, fetched)
helperCompareInformations(t, *contract, fetched)
if contract.Signers[0].Hash != fetched.Signers[0].Hash || contract.Signers[0].Hash != fetched.Signers[1].Hash {
t.Fatal("Signers hash doesn't match")
}
if contract.Signers[0].Email != fetched.Signers[0].Email || contract.Signers[0].Email != fetched.Signers[1].Email {
t.Fatal("Signers hash doesn't match")
}
if contract.Signers[0].UserID != fetched.Signers[0].UserID || contract.Signers[1].UserID != fetched.Signers[1].UserID {
t.Fatal("Signers id doesn't match")
}
fmt.Println("Successfully fetched contract")
}
package user
import (
"dfss/mgdb"
"time"
"gopkg.in/mgo.v2/bson"
)
// ConnectionInfo : Internal connection information of a User
type ConnectionInfo struct {
IP string `key:"ip" bson:"ip"` // Ip of the connection
Port int `key:"port" bson:"port"` // Port of the connection
}
// NewConnectionInfo : Create a new ConnectionInfo
func NewConnectionInfo() *ConnectionInfo {
return &ConnectionInfo{}
}
// User : User stored in mongo
type User struct {
ID bson.ObjectId `key:"_id" bson:"_id"` // Internal id of a User
Email string `key:"email" bson:"email"` // Email of a User
Registration time.Time `key:"registration" bson:"registration"` // Time of registration of the User
RegToken string `key:"regToken" bson:"regToken"` // Token used for registering a User
Csr string `key:"csr" bson:"csr"` // Certificate request at PEM format
Certificate string `key:"certificate" bson:"certificate"` // Certificate of the User
CertHash string `key:"certHash" bson:"certHash"` // Hash of the certificate
ConnInfo ConnectionInfo `key:"connInfo" bson:"connInfo"` // Information about the connection
}
// NewUser : Create a new User
func NewUser() *User {
return &User{
ID: bson.NewObjectId(),
Registration: time.Now().UTC(),
ConnInfo: *NewConnectionInfo(),
}
}
// Repository : Holds all the complex methods regarding a user
type Repository struct {
Collection *mgdb.MongoCollection
}
// NewRepository : Creates a new user repository from the given connection
func NewRepository(collection *mgdb.MongoCollection) *Repository {
return &Repository{
collection,
}
}
// FetchByMailAndHash : Fetches a User from its email and certificate hash
func (repository *Repository) FetchByMailAndHash(email, hash string) (*User, error) {
var users []User
err := repository.Collection.FindAll(bson.M{"email": email, "certHash": hash}, &users)
if err != nil || len(users) == 0 {
return nil, err
}
users[0].Registration = users[0].Registration.UTC()
return &users[0], err
}
package user
import (
"dfss/mgdb"
"fmt"
"os"
"testing"
"gopkg.in/mgo.v2/bson"
)
var err error
var collection *mgdb.MongoCollection
var manager *mgdb.MongoManager
var dbURI string
var repository *Repository
func TestMain(m *testing.M) {
dbURI = os.Getenv("DFSS_MONGO_URI")
if dbURI == "" {
dbURI = "mongodb://localhost/dfss"
}
manager, err = mgdb.NewManager(dbURI)
collection = manager.Get("demo")
repository = NewRepository(collection)
// Run
code := m.Run()
// Teardown
// The collection is created automatically on
// first connection, that's why we do not recreate it manually
err = collection.Drop()
if err != nil {
fmt.Println("An error occurred while droping the collection")
}
manager.Close()
os.Exit(code)
}
func TestMongoFetchInexistantUser(t *testing.T) {
user, erro := repository.FetchByMailAndHash("dummyMail", "dummyHash")
if user != nil || erro != nil {
t.Fatal("User should not have been found and error should be nil")
}
}
func TestMongoInsertUser(t *testing.T) {
user := NewUser()
user.Email = "dfss1@mpcs.tk"
user.CertHash = "dummy_hash"
user.ConnInfo.IP = "127.0.0.1"
user.ConnInfo.Port = 1111
user.Csr = "csr1"
user.RegToken = "regToken 1"
_, err = repository.Collection.Insert(user)
if err != nil {
t.Fatal("An error occurred while inserting the user")
}
fmt.Println("Successfully inserted a user")
}
func equalUsers(t *testing.T, user1, user2 *User) {
if user1.ID != user2.ID {
t.Fatal("ID doesn't match : received ", user1.ID, " and ", user2.ID)
}
if user1.CertHash != user2.CertHash {
t.Fatal("CertHash doesn't match : received ", user1.CertHash, " and ", user2.CertHash)
}
if user1.Email != user2.Email {
t.Fatal("Email doesn't match : received ", user1.Email, " and ", user2.Email)
}
if user1.Registration.Unix() != user2.Registration.Unix() {
t.Fatal("Registration doesn't match : received ", user1.Registration, " and ", user2.Registration)
}
if user1.RegToken != user2.RegToken {
t.Fatal("RegToken doesn't match : received ", user1.RegToken, " and ", user2.RegToken)
}
if user1.Csr != user2.Csr {
t.Fatal("Csr doesn't match : received ", user1.Csr, " and ", user2.Csr)
}
if user1.ConnInfo.IP != user2.ConnInfo.IP {
t.Fatal("ConnInfo.IP doesn't match : received ", user1.ConnInfo.IP, " and ", user2.ConnInfo.IP)
}
if user1.ConnInfo.Port != user2.ConnInfo.Port {
t.Fatal("ConnInfo.Port doesn't match : received ", user1.ConnInfo.Port, " and ", user2.ConnInfo.Port)
}
if user1.Certificate != user2.Certificate {
t.Fatal("Certificate doesn't match : received ", user1.Certificate, " and ", user2.Certificate)
}
}
func TestMongoFetchUser(t *testing.T) {
user := NewUser()
user.Email = "dfss2@mpcs.tk"
user.CertHash = "dummy_hash"
user.ConnInfo.IP = "127.0.0.2"
user.ConnInfo.Port = 2222
user.Csr = "csr2"
user.RegToken = "regToken 2"
_, err = repository.Collection.Insert(user)
if err != nil {
t.Fatal("An error occured while inserting a user: ", err)
}
fetched, erro := repository.FetchByMailAndHash(user.Email, user.CertHash)
if erro != nil {
t.Fatal("An error occurred while fetching the previously inserted user", err)
}
equalUsers(t, user, fetched)
}
func TestMongoFetchIncompleteUser(t *testing.T) {
user := User{
ID: bson.NewObjectId(),
}
_, err = repository.Collection.Insert(user)
if err != nil {
t.Fatal("An error occured while inserting a user: ", err)
}
fetched, erro := repository.FetchByMailAndHash(user.Email, user.CertHash)
if erro != nil {
t.Fatal("An error occurred while fetching the previously inserted user", err)
}
equalUsers(t, &user, fetched)
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment