Register endpoint working
This commit is contained in:
parent
6a6c38f3ee
commit
00f4288c25
@ -1,6 +1,7 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"multitenantStack/models"
|
"multitenantStack/models"
|
||||||
companydb "multitenantStack/services/companydb"
|
companydb "multitenantStack/services/companydb"
|
||||||
|
|
||||||
@ -9,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/astaxie/beego/orm"
|
"github.com/astaxie/beego/orm"
|
||||||
jwt "github.com/dgrijalva/jwt-go"
|
jwt "github.com/dgrijalva/jwt-go"
|
||||||
|
"github.com/kennygrant/sanitize"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AuthController operations for Auth
|
// AuthController operations for Auth
|
||||||
@ -16,14 +18,18 @@ type AuthController struct {
|
|||||||
BaseController
|
BaseController
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AuthResponse the format for all responses from auth
|
||||||
|
type AuthResponse struct {
|
||||||
|
Status int `json:"status"`
|
||||||
|
Jwt string `json:"jwt"`
|
||||||
|
User models.CompanyUser `json:"user"`
|
||||||
|
}
|
||||||
|
|
||||||
// URLMapping ...
|
// URLMapping ...
|
||||||
func (c *AuthController) URLMapping() {
|
func (c *AuthController) URLMapping() {
|
||||||
// This block is used to drastically speed up the annotation -> lookup process
|
// This block is used to drastically speed up the annotation -> lookup process
|
||||||
c.Mapping("Login", c.Login)
|
c.Mapping("Login", c.Login)
|
||||||
c.Mapping("GetOne", c.GetOne)
|
c.Mapping("Register", c.Register)
|
||||||
c.Mapping("GetAll", c.GetAll)
|
|
||||||
c.Mapping("Put", c.Put)
|
|
||||||
c.Mapping("Delete", c.Delete)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login Get a JWT token for the user
|
// Login Get a JWT token for the user
|
||||||
@ -34,13 +40,6 @@ func (c *AuthController) URLMapping() {
|
|||||||
// @Failure 403 body is empty
|
// @Failure 403 body is empty
|
||||||
// @router /login [post]
|
// @router /login [post]
|
||||||
func (c *AuthController) Login() {
|
func (c *AuthController) Login() {
|
||||||
|
|
||||||
type AuthResponse struct {
|
|
||||||
Status int `json:"status"`
|
|
||||||
Jwt string `json:"jwt"`
|
|
||||||
User models.CompanyUser `json:"user"`
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Ctx.Input.Method() != "POST" {
|
if c.Ctx.Input.Method() != "POST" {
|
||||||
c.ServeJSONError("Method not allowed")
|
c.ServeJSONError("Method not allowed")
|
||||||
return
|
return
|
||||||
@ -127,52 +126,135 @@ func (c *AuthController) Login() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOne ...
|
// Register Register a new company and user, create DB and so on
|
||||||
// @Title GetOne
|
// @Title Create
|
||||||
// @Description get Auth by id
|
// @Description create Auth
|
||||||
// @Param id path string true "The key for staticblock"
|
|
||||||
// @Success 200 {object} models.Auth
|
|
||||||
// @Failure 403 :id is empty
|
|
||||||
// @router /:id [get]
|
|
||||||
func (c *AuthController) GetOne() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAll ...
|
|
||||||
// @Title GetAll
|
|
||||||
// @Description get Auth
|
|
||||||
// @Param query query string false "Filter. e.g. col1:v1,col2:v2 ..."
|
|
||||||
// @Param fields query string false "Fields returned. e.g. col1,col2 ..."
|
|
||||||
// @Param sortby query string false "Sorted-by fields. e.g. col1,col2 ..."
|
|
||||||
// @Param order query string false "Order corresponding to each sortby field, if single value, apply to all sortby fields. e.g. desc,asc ..."
|
|
||||||
// @Param limit query string false "Limit the size of result set. Must be an integer"
|
|
||||||
// @Param offset query string false "Start position of result set. Must be an integer"
|
|
||||||
// @Success 200 {object} models.Auth
|
|
||||||
// @Failure 403
|
|
||||||
// @router / [get]
|
|
||||||
func (c *AuthController) GetAll() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Put ...
|
|
||||||
// @Title Put
|
|
||||||
// @Description update the Auth
|
|
||||||
// @Param id path string true "The id you want to update"
|
|
||||||
// @Param body body models.Auth true "body for Auth content"
|
// @Param body body models.Auth true "body for Auth content"
|
||||||
// @Success 200 {object} models.Auth
|
// @Success 201 {object} models.Auth
|
||||||
// @Failure 403 :id is not int
|
// @Failure 403 body is empty
|
||||||
// @router /:id [put]
|
// @router /register [post]
|
||||||
func (c *AuthController) Put() {
|
func (c *AuthController) Register() {
|
||||||
|
// can be called without jwt token set
|
||||||
}
|
|
||||||
|
// needed data:
|
||||||
// Delete ...
|
// email
|
||||||
// @Title Delete
|
// password
|
||||||
// @Description delete the Auth
|
// companyname
|
||||||
// @Param id path string true "The id you want to delete"
|
// optional: username
|
||||||
// @Success 200 {string} delete success!
|
|
||||||
// @Failure 403 id is empty
|
// Tasks:
|
||||||
// @router /:id [delete]
|
// create database
|
||||||
func (c *AuthController) Delete() {
|
// create user_company_map entry
|
||||||
|
// create company user
|
||||||
|
// return jwt token and user profile
|
||||||
|
|
||||||
|
if c.Ctx.Input.Method() != "POST" {
|
||||||
|
c.ServeJSONError("Method not allowed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenHeader := c.Ctx.Request.Header.Get("X-JWTtoken")
|
||||||
|
if tokenHeader != "" {
|
||||||
|
valid, _ := tokenTools.Validate(tokenHeader)
|
||||||
|
if valid {
|
||||||
|
c.ServeJSONError("You are already logged in")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
email := c.GetString("email")
|
||||||
|
password := c.GetString("password")
|
||||||
|
username := c.GetString("username")
|
||||||
|
companyname := c.GetString("companyname")
|
||||||
|
|
||||||
|
companyname = sanitize.BaseName(companyname)
|
||||||
|
companyname = fmt.Sprintf("company_%s", companyname)
|
||||||
|
|
||||||
|
if email == "" || password == "" || companyname == "" || username == "" {
|
||||||
|
c.ServeJSONError("Email/Password/Companyname missing")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
systemdb := companydb.GetSystemDatabase()
|
||||||
|
|
||||||
|
if systemdb == nil {
|
||||||
|
c.ServeJSONError("Error retrieving data")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
o, err := orm.NewOrmWithDB("postgres", "default", systemdb)
|
||||||
|
if err != nil {
|
||||||
|
c.ServeJSONError("Error retrieving data")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ucmExists, err := models.GetUserCompanyMapByEmail(o, email)
|
||||||
|
if err != nil && ucmExists != nil {
|
||||||
|
c.ServeJSONError("Error: Email exists!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if companydb.HasDatabase(companyname) {
|
||||||
|
c.ServeJSONError("Error: Company exists!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var userCompanyMapping models.UserCompanyMap
|
||||||
|
newHash, _ := tokenTools.HashPassword(password)
|
||||||
|
userCompanyMapping.PasswordHash = newHash
|
||||||
|
userCompanyMapping.Company = companyname
|
||||||
|
userCompanyMapping.Email = email
|
||||||
|
|
||||||
|
ucmID, err := models.AddUserCompanyMap(o, &userCompanyMapping)
|
||||||
|
if err != nil {
|
||||||
|
c.ServeJSONErrorWithError("Error on saving user", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create company
|
||||||
|
newDB, err := companydb.CreateDatabase(companyname)
|
||||||
|
if err != nil {
|
||||||
|
c.ServeJSONErrorWithError("Error on creating DB", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
newO, err := orm.NewOrmWithDB("postgres", "default", newDB)
|
||||||
|
if err != nil {
|
||||||
|
c.ServeJSONErrorWithError("Error retrieving company data", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var companyUser models.CompanyUser
|
||||||
|
companyUser.Name = username
|
||||||
|
companyUser.Profile = "{}"
|
||||||
|
companyUser.Role = 1 //TODO: replacxe with owner constant
|
||||||
|
|
||||||
|
userID, err := models.AddCompanyUser(newO, &companyUser)
|
||||||
|
if err != nil {
|
||||||
|
c.ServeJSONError("Error on saving company user")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// edit usermapping
|
||||||
|
userCompanyMapping.ID = int(ucmID)
|
||||||
|
userCompanyMapping.CompanyUserID = int16(userID)
|
||||||
|
if err := models.UpdateUserCompanyMapById(o, &userCompanyMapping); err != nil {
|
||||||
|
c.ServeJSONError("Error on saving user")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tokenString := ""
|
||||||
|
|
||||||
|
tokenString = tokenTools.CreateToken(jwt.MapClaims{
|
||||||
|
"email": email,
|
||||||
|
"companyName": companyname,
|
||||||
|
"companyUserID": userCompanyMapping.CompanyUserID,
|
||||||
|
"exp": time.Now().Unix() + 3600,
|
||||||
|
})
|
||||||
|
|
||||||
|
json := AuthResponse{200, tokenString, companyUser}
|
||||||
|
c.Data["json"] = &json
|
||||||
|
|
||||||
|
c.ServeJSON()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package controllers
|
package controllers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/astaxie/beego"
|
"github.com/astaxie/beego"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,6 +41,15 @@ func (c *BaseController) ServeJSONErrorWithCode(errorcode int, message string) {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ServeJSONErrorWithError respond with a JSON error and print an error message
|
||||||
|
func (c *BaseController) ServeJSONErrorWithError(message string, err error) {
|
||||||
|
message = fmt.Sprintf("%s %s", message, err.Error())
|
||||||
|
json := JSONBasicResponse{JSONError, message}
|
||||||
|
c.Data["json"] = &json
|
||||||
|
///c.Ctx.ResponseWriter.WriteHeader(400)
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
// ServeJSONSuccess respond with a JSON success message
|
// ServeJSONSuccess respond with a JSON success message
|
||||||
func (c *BaseController) ServeJSONSuccess(message string) {
|
func (c *BaseController) ServeJSONSuccess(message string) {
|
||||||
json := JSONBasicResponse{JSONSuccess, message}
|
json := JSONBasicResponse{JSONSuccess, message}
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type UserCompanyMap struct {
|
type UserCompanyMap struct {
|
||||||
ID int `orm:"column(id);pk"`
|
ID int `orm:"column(id)"` // removed pk here to fix postgres error
|
||||||
Email string `orm:"column(email)"`
|
Email string `orm:"column(email)"`
|
||||||
PasswordHash string `orm:"column(password_hash)"`
|
PasswordHash string `orm:"column(password_hash)"`
|
||||||
Company string `orm:"column(company)"`
|
Company string `orm:"column(company)"`
|
||||||
|
@ -68,8 +68,6 @@ func GetDatabaseWithName(companyName string) (*sql.DB, error) {
|
|||||||
return db, nil
|
return db, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: call upper function in this one to reduce code
|
|
||||||
|
|
||||||
// GetDatabase Get orm and user information
|
// GetDatabase Get orm and user information
|
||||||
func GetDatabase(tokenString string) (jwt.MapClaims, *sql.DB, error) {
|
func GetDatabase(tokenString string) (jwt.MapClaims, *sql.DB, error) {
|
||||||
// validate token
|
// validate token
|
||||||
@ -86,9 +84,7 @@ func GetDatabase(tokenString string) (jwt.MapClaims, *sql.DB, error) {
|
|||||||
return tokenMap, dbs[companyName], nil
|
return tokenMap, dbs[companyName], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
conStr := fmt.Sprintf("host=127.0.0.1 port=5435 user=postgres password=postgre dbname=%s sslmode=disable", companyName)
|
db, err := GetDatabaseWithName(companyName)
|
||||||
fmt.Println(conStr)
|
|
||||||
db, err := sql.Open("postgres", conStr)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -97,36 +93,63 @@ func GetDatabase(tokenString string) (jwt.MapClaims, *sql.DB, error) {
|
|||||||
return tokenMap, db, nil
|
return tokenMap, db, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateDatabase Create a database by copying the template
|
// HasDatabase Check if DB exists
|
||||||
func CreateDatabase(companyName string) {
|
func HasDatabase(dbname string) bool {
|
||||||
/*
|
systemDB := GetSystemDatabase()
|
||||||
if dbs[companyName] != nil {
|
result, err := systemDB.Query("SELECT datname FROM pg_database WHERE datistemplate = false;")
|
||||||
fmt.Println("DB Already open")
|
|
||||||
return dbs[companyName], nil
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
db, err = sql.Open("postgres", "host=127.0.0.1 port=5435 user=postgres password=postgre dbname=company5 sslmode=disable")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
or, err := orm.NewOrmWithDB("postgres", "temp", db)
|
for result.Next() {
|
||||||
*/
|
var aDbName string
|
||||||
|
result.Scan(&aDbName)
|
||||||
|
if aDbName == dbname {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateDatabase Create a database by copying the template
|
||||||
|
func CreateDatabase(companyName string) (*sql.DB, error) {
|
||||||
|
if HasDatabase(companyName) {
|
||||||
|
return nil, errors.New("DB already exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
systemDB := GetSystemDatabase()
|
||||||
|
// Takes about 1.2 seconds and we trust companyName to be sanitized in register
|
||||||
|
queryString := fmt.Sprintf("CREATE DATABASE %s TEMPLATE company_template;", companyName)
|
||||||
|
_, err := systemDB.Exec(queryString)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := GetDatabaseWithName(companyName)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return db, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteDatabase Delete an entire database, this is very very dangerous :-)
|
// DeleteDatabase Delete an entire database, this is very very dangerous :-)
|
||||||
func DeleteDatabase(token string) {
|
func DeleteDatabase(companyName string) error {
|
||||||
//_, db, err := GetDatabase(token)
|
if !HasDatabase(companyName) {
|
||||||
/*
|
return errors.New("DB does not exist")
|
||||||
remove from map!
|
|
||||||
db.Close()
|
|
||||||
fmt.Println("Closed company5")
|
|
||||||
//}
|
|
||||||
|
|
||||||
res, err := o.Raw("DROP DATABASE company5;").Exec()
|
|
||||||
if err == nil {
|
|
||||||
num, _ := res.RowsAffected()
|
|
||||||
fmt.Println("mysql row affected number: ", num)
|
|
||||||
}
|
}
|
||||||
*/
|
systemDB := GetSystemDatabase()
|
||||||
|
|
||||||
|
db, err := GetDatabaseWithName(companyName)
|
||||||
|
db.Close()
|
||||||
|
delete(dbs, companyName)
|
||||||
|
fmt.Println("Closed %s", companyName)
|
||||||
|
|
||||||
|
queryString := fmt.Sprintf("DROP DATABASE %s;", companyName)
|
||||||
|
_, err = systemDB.Exec(queryString)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user