align types with new db schema

This commit is contained in:
Hayden 2022-08-30 10:05:11 -08:00
parent 63cfeffc4d
commit b83505104a
30 changed files with 1491 additions and 263 deletions

View File

@ -80,7 +80,7 @@ const docTemplate = `{
"item": {
"type": "array",
"items": {
"$ref": "#/definitions/types.UserOut"
"$ref": "#/definitions/ent.User"
}
}
}
@ -126,7 +126,7 @@ const docTemplate = `{
"type": "object",
"properties": {
"item": {
"$ref": "#/definitions/types.UserOut"
"$ref": "#/definitions/ent.User"
}
}
}
@ -171,7 +171,7 @@ const docTemplate = `{
"type": "object",
"properties": {
"item": {
"$ref": "#/definitions/types.UserOut"
"$ref": "#/definitions/ent.User"
}
}
}
@ -223,7 +223,7 @@ const docTemplate = `{
"type": "object",
"properties": {
"item": {
"$ref": "#/definitions/types.UserOut"
"$ref": "#/definitions/ent.User"
}
}
}
@ -337,6 +337,48 @@ const docTemplate = `{
}
}
},
"/v1/users/register": {
"post": {
"produces": [
"application/json"
],
"tags": [
"User"
],
"summary": "Get the current user",
"parameters": [
{
"description": "User Data",
"name": "payload",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/types.UserRegistration"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/server.Result"
},
{
"type": "object",
"properties": {
"item": {
"$ref": "#/definitions/ent.User"
}
}
}
]
}
}
}
}
},
"/v1/users/self": {
"get": {
"security": [
@ -363,7 +405,7 @@ const docTemplate = `{
"type": "object",
"properties": {
"item": {
"$ref": "#/definitions/types.UserOut"
"$ref": "#/definitions/ent.User"
}
}
}
@ -441,6 +483,418 @@ const docTemplate = `{
}
},
"definitions": {
"ent.AuthTokens": {
"type": "object",
"properties": {
"created_at": {
"description": "CreatedAt holds the value of the \"created_at\" field.",
"type": "string"
},
"edges": {
"description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the AuthTokensQuery when eager-loading is set.",
"$ref": "#/definitions/ent.AuthTokensEdges"
},
"expires_at": {
"description": "ExpiresAt holds the value of the \"expires_at\" field.",
"type": "string"
},
"id": {
"description": "ID of the ent.",
"type": "string"
},
"token": {
"description": "Token holds the value of the \"token\" field.",
"type": "array",
"items": {
"type": "integer"
}
},
"updated_at": {
"description": "UpdatedAt holds the value of the \"updated_at\" field.",
"type": "string"
}
}
},
"ent.AuthTokensEdges": {
"type": "object",
"properties": {
"user": {
"description": "User holds the value of the user edge.",
"$ref": "#/definitions/ent.User"
}
}
},
"ent.Group": {
"type": "object",
"properties": {
"created_at": {
"description": "CreatedAt holds the value of the \"created_at\" field.",
"type": "string"
},
"currency": {
"description": "Currency holds the value of the \"currency\" field.",
"type": "string"
},
"edges": {
"description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the GroupQuery when eager-loading is set.",
"$ref": "#/definitions/ent.GroupEdges"
},
"id": {
"description": "ID of the ent.",
"type": "string"
},
"name": {
"description": "Name holds the value of the \"name\" field.",
"type": "string"
},
"updated_at": {
"description": "UpdatedAt holds the value of the \"updated_at\" field.",
"type": "string"
}
}
},
"ent.GroupEdges": {
"type": "object",
"properties": {
"items": {
"description": "Items holds the value of the items edge.",
"type": "array",
"items": {
"$ref": "#/definitions/ent.Item"
}
},
"labels": {
"description": "Labels holds the value of the labels edge.",
"type": "array",
"items": {
"$ref": "#/definitions/ent.Label"
}
},
"locations": {
"description": "Locations holds the value of the locations edge.",
"type": "array",
"items": {
"$ref": "#/definitions/ent.Location"
}
},
"users": {
"description": "Users holds the value of the users edge.",
"type": "array",
"items": {
"$ref": "#/definitions/ent.User"
}
}
}
},
"ent.Item": {
"type": "object",
"properties": {
"created_at": {
"description": "CreatedAt holds the value of the \"created_at\" field.",
"type": "string"
},
"description": {
"description": "Description holds the value of the \"description\" field.",
"type": "string"
},
"edges": {
"description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the ItemQuery when eager-loading is set.",
"$ref": "#/definitions/ent.ItemEdges"
},
"id": {
"description": "ID of the ent.",
"type": "string"
},
"manufacturer": {
"description": "Manufacturer holds the value of the \"manufacturer\" field.",
"type": "string"
},
"model_number": {
"description": "ModelNumber holds the value of the \"model_number\" field.",
"type": "string"
},
"name": {
"description": "Name holds the value of the \"name\" field.",
"type": "string"
},
"notes": {
"description": "Notes holds the value of the \"notes\" field.",
"type": "string"
},
"purchase_from": {
"description": "PurchaseFrom holds the value of the \"purchase_from\" field.",
"type": "string"
},
"purchase_price": {
"description": "PurchasePrice holds the value of the \"purchase_price\" field.",
"type": "number"
},
"purchase_receipt_id": {
"description": "PurchaseReceiptID holds the value of the \"purchase_receipt_id\" field.",
"type": "string"
},
"purchase_time": {
"description": "PurchaseTime holds the value of the \"purchase_time\" field.",
"type": "string"
},
"serial_number": {
"description": "SerialNumber holds the value of the \"serial_number\" field.",
"type": "string"
},
"sold_notes": {
"description": "SoldNotes holds the value of the \"sold_notes\" field.",
"type": "string"
},
"sold_price": {
"description": "SoldPrice holds the value of the \"sold_price\" field.",
"type": "number"
},
"sold_receipt_id": {
"description": "SoldReceiptID holds the value of the \"sold_receipt_id\" field.",
"type": "string"
},
"sold_time": {
"description": "SoldTime holds the value of the \"sold_time\" field.",
"type": "string"
},
"sold_to": {
"description": "SoldTo holds the value of the \"sold_to\" field.",
"type": "string"
},
"updated_at": {
"description": "UpdatedAt holds the value of the \"updated_at\" field.",
"type": "string"
}
}
},
"ent.ItemEdges": {
"type": "object",
"properties": {
"fields": {
"description": "Fields holds the value of the fields edge.",
"type": "array",
"items": {
"$ref": "#/definitions/ent.ItemField"
}
},
"group": {
"description": "Group holds the value of the group edge.",
"$ref": "#/definitions/ent.Group"
},
"label": {
"description": "Label holds the value of the label edge.",
"type": "array",
"items": {
"$ref": "#/definitions/ent.Label"
}
},
"location": {
"description": "Location holds the value of the location edge.",
"$ref": "#/definitions/ent.Location"
}
}
},
"ent.ItemField": {
"type": "object",
"properties": {
"boolean_value": {
"description": "BooleanValue holds the value of the \"boolean_value\" field.",
"type": "boolean"
},
"created_at": {
"description": "CreatedAt holds the value of the \"created_at\" field.",
"type": "string"
},
"description": {
"description": "Description holds the value of the \"description\" field.",
"type": "string"
},
"edges": {
"description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the ItemFieldQuery when eager-loading is set.",
"$ref": "#/definitions/ent.ItemFieldEdges"
},
"id": {
"description": "ID of the ent.",
"type": "string"
},
"name": {
"description": "Name holds the value of the \"name\" field.",
"type": "string"
},
"number_value": {
"description": "NumberValue holds the value of the \"number_value\" field.",
"type": "integer"
},
"text_value": {
"description": "TextValue holds the value of the \"text_value\" field.",
"type": "string"
},
"time_value": {
"description": "TimeValue holds the value of the \"time_value\" field.",
"type": "string"
},
"type": {
"description": "Type holds the value of the \"type\" field.",
"type": "string"
},
"updated_at": {
"description": "UpdatedAt holds the value of the \"updated_at\" field.",
"type": "string"
}
}
},
"ent.ItemFieldEdges": {
"type": "object",
"properties": {
"item": {
"description": "Item holds the value of the item edge.",
"$ref": "#/definitions/ent.Item"
}
}
},
"ent.Label": {
"type": "object",
"properties": {
"color": {
"description": "Color holds the value of the \"color\" field.",
"type": "string"
},
"created_at": {
"description": "CreatedAt holds the value of the \"created_at\" field.",
"type": "string"
},
"description": {
"description": "Description holds the value of the \"description\" field.",
"type": "string"
},
"edges": {
"description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the LabelQuery when eager-loading is set.",
"$ref": "#/definitions/ent.LabelEdges"
},
"id": {
"description": "ID of the ent.",
"type": "string"
},
"name": {
"description": "Name holds the value of the \"name\" field.",
"type": "string"
},
"updated_at": {
"description": "UpdatedAt holds the value of the \"updated_at\" field.",
"type": "string"
}
}
},
"ent.LabelEdges": {
"type": "object",
"properties": {
"group": {
"description": "Group holds the value of the group edge.",
"$ref": "#/definitions/ent.Group"
},
"items": {
"description": "Items holds the value of the items edge.",
"type": "array",
"items": {
"$ref": "#/definitions/ent.Item"
}
}
}
},
"ent.Location": {
"type": "object",
"properties": {
"created_at": {
"description": "CreatedAt holds the value of the \"created_at\" field.",
"type": "string"
},
"description": {
"description": "Description holds the value of the \"description\" field.",
"type": "string"
},
"edges": {
"description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the LocationQuery when eager-loading is set.",
"$ref": "#/definitions/ent.LocationEdges"
},
"id": {
"description": "ID of the ent.",
"type": "string"
},
"name": {
"description": "Name holds the value of the \"name\" field.",
"type": "string"
},
"updated_at": {
"description": "UpdatedAt holds the value of the \"updated_at\" field.",
"type": "string"
}
}
},
"ent.LocationEdges": {
"type": "object",
"properties": {
"group": {
"description": "Group holds the value of the group edge.",
"$ref": "#/definitions/ent.Group"
},
"items": {
"description": "Items holds the value of the items edge.",
"type": "array",
"items": {
"$ref": "#/definitions/ent.Item"
}
}
}
},
"ent.User": {
"type": "object",
"properties": {
"created_at": {
"description": "CreatedAt holds the value of the \"created_at\" field.",
"type": "string"
},
"edges": {
"description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the UserQuery when eager-loading is set.",
"$ref": "#/definitions/ent.UserEdges"
},
"email": {
"description": "Email holds the value of the \"email\" field.",
"type": "string"
},
"id": {
"description": "ID of the ent.",
"type": "string"
},
"is_superuser": {
"description": "IsSuperuser holds the value of the \"is_superuser\" field.",
"type": "boolean"
},
"name": {
"description": "Name holds the value of the \"name\" field.",
"type": "string"
},
"updated_at": {
"description": "UpdatedAt holds the value of the \"updated_at\" field.",
"type": "string"
}
}
},
"ent.UserEdges": {
"type": "object",
"properties": {
"auth_tokens": {
"description": "AuthTokens holds the value of the auth_tokens edge.",
"type": "array",
"items": {
"$ref": "#/definitions/ent.AuthTokens"
}
},
"group": {
"description": "Group holds the value of the group edge.",
"$ref": "#/definitions/ent.Group"
}
}
},
"server.Result": {
"type": "object",
"properties": {
@ -491,6 +945,9 @@ const docTemplate = `{
"email": {
"type": "string"
},
"groupID": {
"type": "string"
},
"isSuperuser": {
"type": "boolean"
},
@ -502,20 +959,28 @@ const docTemplate = `{
}
}
},
"types.UserOut": {
"types.UserIn": {
"type": "object",
"properties": {
"email": {
"type": "string"
},
"id": {
"type": "string"
},
"isSuperuser": {
"type": "boolean"
},
"name": {
"type": "string"
},
"password": {
"type": "string"
}
}
},
"types.UserRegistration": {
"type": "object",
"properties": {
"groupName": {
"type": "string"
},
"user": {
"$ref": "#/definitions/types.UserIn"
}
}
},

View File

@ -72,7 +72,7 @@
"item": {
"type": "array",
"items": {
"$ref": "#/definitions/types.UserOut"
"$ref": "#/definitions/ent.User"
}
}
}
@ -118,7 +118,7 @@
"type": "object",
"properties": {
"item": {
"$ref": "#/definitions/types.UserOut"
"$ref": "#/definitions/ent.User"
}
}
}
@ -163,7 +163,7 @@
"type": "object",
"properties": {
"item": {
"$ref": "#/definitions/types.UserOut"
"$ref": "#/definitions/ent.User"
}
}
}
@ -215,7 +215,7 @@
"type": "object",
"properties": {
"item": {
"$ref": "#/definitions/types.UserOut"
"$ref": "#/definitions/ent.User"
}
}
}
@ -329,6 +329,48 @@
}
}
},
"/v1/users/register": {
"post": {
"produces": [
"application/json"
],
"tags": [
"User"
],
"summary": "Get the current user",
"parameters": [
{
"description": "User Data",
"name": "payload",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/types.UserRegistration"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"allOf": [
{
"$ref": "#/definitions/server.Result"
},
{
"type": "object",
"properties": {
"item": {
"$ref": "#/definitions/ent.User"
}
}
}
]
}
}
}
}
},
"/v1/users/self": {
"get": {
"security": [
@ -355,7 +397,7 @@
"type": "object",
"properties": {
"item": {
"$ref": "#/definitions/types.UserOut"
"$ref": "#/definitions/ent.User"
}
}
}
@ -433,6 +475,418 @@
}
},
"definitions": {
"ent.AuthTokens": {
"type": "object",
"properties": {
"created_at": {
"description": "CreatedAt holds the value of the \"created_at\" field.",
"type": "string"
},
"edges": {
"description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the AuthTokensQuery when eager-loading is set.",
"$ref": "#/definitions/ent.AuthTokensEdges"
},
"expires_at": {
"description": "ExpiresAt holds the value of the \"expires_at\" field.",
"type": "string"
},
"id": {
"description": "ID of the ent.",
"type": "string"
},
"token": {
"description": "Token holds the value of the \"token\" field.",
"type": "array",
"items": {
"type": "integer"
}
},
"updated_at": {
"description": "UpdatedAt holds the value of the \"updated_at\" field.",
"type": "string"
}
}
},
"ent.AuthTokensEdges": {
"type": "object",
"properties": {
"user": {
"description": "User holds the value of the user edge.",
"$ref": "#/definitions/ent.User"
}
}
},
"ent.Group": {
"type": "object",
"properties": {
"created_at": {
"description": "CreatedAt holds the value of the \"created_at\" field.",
"type": "string"
},
"currency": {
"description": "Currency holds the value of the \"currency\" field.",
"type": "string"
},
"edges": {
"description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the GroupQuery when eager-loading is set.",
"$ref": "#/definitions/ent.GroupEdges"
},
"id": {
"description": "ID of the ent.",
"type": "string"
},
"name": {
"description": "Name holds the value of the \"name\" field.",
"type": "string"
},
"updated_at": {
"description": "UpdatedAt holds the value of the \"updated_at\" field.",
"type": "string"
}
}
},
"ent.GroupEdges": {
"type": "object",
"properties": {
"items": {
"description": "Items holds the value of the items edge.",
"type": "array",
"items": {
"$ref": "#/definitions/ent.Item"
}
},
"labels": {
"description": "Labels holds the value of the labels edge.",
"type": "array",
"items": {
"$ref": "#/definitions/ent.Label"
}
},
"locations": {
"description": "Locations holds the value of the locations edge.",
"type": "array",
"items": {
"$ref": "#/definitions/ent.Location"
}
},
"users": {
"description": "Users holds the value of the users edge.",
"type": "array",
"items": {
"$ref": "#/definitions/ent.User"
}
}
}
},
"ent.Item": {
"type": "object",
"properties": {
"created_at": {
"description": "CreatedAt holds the value of the \"created_at\" field.",
"type": "string"
},
"description": {
"description": "Description holds the value of the \"description\" field.",
"type": "string"
},
"edges": {
"description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the ItemQuery when eager-loading is set.",
"$ref": "#/definitions/ent.ItemEdges"
},
"id": {
"description": "ID of the ent.",
"type": "string"
},
"manufacturer": {
"description": "Manufacturer holds the value of the \"manufacturer\" field.",
"type": "string"
},
"model_number": {
"description": "ModelNumber holds the value of the \"model_number\" field.",
"type": "string"
},
"name": {
"description": "Name holds the value of the \"name\" field.",
"type": "string"
},
"notes": {
"description": "Notes holds the value of the \"notes\" field.",
"type": "string"
},
"purchase_from": {
"description": "PurchaseFrom holds the value of the \"purchase_from\" field.",
"type": "string"
},
"purchase_price": {
"description": "PurchasePrice holds the value of the \"purchase_price\" field.",
"type": "number"
},
"purchase_receipt_id": {
"description": "PurchaseReceiptID holds the value of the \"purchase_receipt_id\" field.",
"type": "string"
},
"purchase_time": {
"description": "PurchaseTime holds the value of the \"purchase_time\" field.",
"type": "string"
},
"serial_number": {
"description": "SerialNumber holds the value of the \"serial_number\" field.",
"type": "string"
},
"sold_notes": {
"description": "SoldNotes holds the value of the \"sold_notes\" field.",
"type": "string"
},
"sold_price": {
"description": "SoldPrice holds the value of the \"sold_price\" field.",
"type": "number"
},
"sold_receipt_id": {
"description": "SoldReceiptID holds the value of the \"sold_receipt_id\" field.",
"type": "string"
},
"sold_time": {
"description": "SoldTime holds the value of the \"sold_time\" field.",
"type": "string"
},
"sold_to": {
"description": "SoldTo holds the value of the \"sold_to\" field.",
"type": "string"
},
"updated_at": {
"description": "UpdatedAt holds the value of the \"updated_at\" field.",
"type": "string"
}
}
},
"ent.ItemEdges": {
"type": "object",
"properties": {
"fields": {
"description": "Fields holds the value of the fields edge.",
"type": "array",
"items": {
"$ref": "#/definitions/ent.ItemField"
}
},
"group": {
"description": "Group holds the value of the group edge.",
"$ref": "#/definitions/ent.Group"
},
"label": {
"description": "Label holds the value of the label edge.",
"type": "array",
"items": {
"$ref": "#/definitions/ent.Label"
}
},
"location": {
"description": "Location holds the value of the location edge.",
"$ref": "#/definitions/ent.Location"
}
}
},
"ent.ItemField": {
"type": "object",
"properties": {
"boolean_value": {
"description": "BooleanValue holds the value of the \"boolean_value\" field.",
"type": "boolean"
},
"created_at": {
"description": "CreatedAt holds the value of the \"created_at\" field.",
"type": "string"
},
"description": {
"description": "Description holds the value of the \"description\" field.",
"type": "string"
},
"edges": {
"description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the ItemFieldQuery when eager-loading is set.",
"$ref": "#/definitions/ent.ItemFieldEdges"
},
"id": {
"description": "ID of the ent.",
"type": "string"
},
"name": {
"description": "Name holds the value of the \"name\" field.",
"type": "string"
},
"number_value": {
"description": "NumberValue holds the value of the \"number_value\" field.",
"type": "integer"
},
"text_value": {
"description": "TextValue holds the value of the \"text_value\" field.",
"type": "string"
},
"time_value": {
"description": "TimeValue holds the value of the \"time_value\" field.",
"type": "string"
},
"type": {
"description": "Type holds the value of the \"type\" field.",
"type": "string"
},
"updated_at": {
"description": "UpdatedAt holds the value of the \"updated_at\" field.",
"type": "string"
}
}
},
"ent.ItemFieldEdges": {
"type": "object",
"properties": {
"item": {
"description": "Item holds the value of the item edge.",
"$ref": "#/definitions/ent.Item"
}
}
},
"ent.Label": {
"type": "object",
"properties": {
"color": {
"description": "Color holds the value of the \"color\" field.",
"type": "string"
},
"created_at": {
"description": "CreatedAt holds the value of the \"created_at\" field.",
"type": "string"
},
"description": {
"description": "Description holds the value of the \"description\" field.",
"type": "string"
},
"edges": {
"description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the LabelQuery when eager-loading is set.",
"$ref": "#/definitions/ent.LabelEdges"
},
"id": {
"description": "ID of the ent.",
"type": "string"
},
"name": {
"description": "Name holds the value of the \"name\" field.",
"type": "string"
},
"updated_at": {
"description": "UpdatedAt holds the value of the \"updated_at\" field.",
"type": "string"
}
}
},
"ent.LabelEdges": {
"type": "object",
"properties": {
"group": {
"description": "Group holds the value of the group edge.",
"$ref": "#/definitions/ent.Group"
},
"items": {
"description": "Items holds the value of the items edge.",
"type": "array",
"items": {
"$ref": "#/definitions/ent.Item"
}
}
}
},
"ent.Location": {
"type": "object",
"properties": {
"created_at": {
"description": "CreatedAt holds the value of the \"created_at\" field.",
"type": "string"
},
"description": {
"description": "Description holds the value of the \"description\" field.",
"type": "string"
},
"edges": {
"description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the LocationQuery when eager-loading is set.",
"$ref": "#/definitions/ent.LocationEdges"
},
"id": {
"description": "ID of the ent.",
"type": "string"
},
"name": {
"description": "Name holds the value of the \"name\" field.",
"type": "string"
},
"updated_at": {
"description": "UpdatedAt holds the value of the \"updated_at\" field.",
"type": "string"
}
}
},
"ent.LocationEdges": {
"type": "object",
"properties": {
"group": {
"description": "Group holds the value of the group edge.",
"$ref": "#/definitions/ent.Group"
},
"items": {
"description": "Items holds the value of the items edge.",
"type": "array",
"items": {
"$ref": "#/definitions/ent.Item"
}
}
}
},
"ent.User": {
"type": "object",
"properties": {
"created_at": {
"description": "CreatedAt holds the value of the \"created_at\" field.",
"type": "string"
},
"edges": {
"description": "Edges holds the relations/edges for other nodes in the graph.\nThe values are being populated by the UserQuery when eager-loading is set.",
"$ref": "#/definitions/ent.UserEdges"
},
"email": {
"description": "Email holds the value of the \"email\" field.",
"type": "string"
},
"id": {
"description": "ID of the ent.",
"type": "string"
},
"is_superuser": {
"description": "IsSuperuser holds the value of the \"is_superuser\" field.",
"type": "boolean"
},
"name": {
"description": "Name holds the value of the \"name\" field.",
"type": "string"
},
"updated_at": {
"description": "UpdatedAt holds the value of the \"updated_at\" field.",
"type": "string"
}
}
},
"ent.UserEdges": {
"type": "object",
"properties": {
"auth_tokens": {
"description": "AuthTokens holds the value of the auth_tokens edge.",
"type": "array",
"items": {
"$ref": "#/definitions/ent.AuthTokens"
}
},
"group": {
"description": "Group holds the value of the group edge.",
"$ref": "#/definitions/ent.Group"
}
}
},
"server.Result": {
"type": "object",
"properties": {
@ -483,6 +937,9 @@
"email": {
"type": "string"
},
"groupID": {
"type": "string"
},
"isSuperuser": {
"type": "boolean"
},
@ -494,20 +951,28 @@
}
}
},
"types.UserOut": {
"types.UserIn": {
"type": "object",
"properties": {
"email": {
"type": "string"
},
"id": {
"type": "string"
},
"isSuperuser": {
"type": "boolean"
},
"name": {
"type": "string"
},
"password": {
"type": "string"
}
}
},
"types.UserRegistration": {
"type": "object",
"properties": {
"groupName": {
"type": "string"
},
"user": {
"$ref": "#/definitions/types.UserIn"
}
}
},

View File

@ -1,5 +1,316 @@
basePath: /api
definitions:
ent.AuthTokens:
properties:
created_at:
description: CreatedAt holds the value of the "created_at" field.
type: string
edges:
$ref: '#/definitions/ent.AuthTokensEdges'
description: |-
Edges holds the relations/edges for other nodes in the graph.
The values are being populated by the AuthTokensQuery when eager-loading is set.
expires_at:
description: ExpiresAt holds the value of the "expires_at" field.
type: string
id:
description: ID of the ent.
type: string
token:
description: Token holds the value of the "token" field.
items:
type: integer
type: array
updated_at:
description: UpdatedAt holds the value of the "updated_at" field.
type: string
type: object
ent.AuthTokensEdges:
properties:
user:
$ref: '#/definitions/ent.User'
description: User holds the value of the user edge.
type: object
ent.Group:
properties:
created_at:
description: CreatedAt holds the value of the "created_at" field.
type: string
currency:
description: Currency holds the value of the "currency" field.
type: string
edges:
$ref: '#/definitions/ent.GroupEdges'
description: |-
Edges holds the relations/edges for other nodes in the graph.
The values are being populated by the GroupQuery when eager-loading is set.
id:
description: ID of the ent.
type: string
name:
description: Name holds the value of the "name" field.
type: string
updated_at:
description: UpdatedAt holds the value of the "updated_at" field.
type: string
type: object
ent.GroupEdges:
properties:
items:
description: Items holds the value of the items edge.
items:
$ref: '#/definitions/ent.Item'
type: array
labels:
description: Labels holds the value of the labels edge.
items:
$ref: '#/definitions/ent.Label'
type: array
locations:
description: Locations holds the value of the locations edge.
items:
$ref: '#/definitions/ent.Location'
type: array
users:
description: Users holds the value of the users edge.
items:
$ref: '#/definitions/ent.User'
type: array
type: object
ent.Item:
properties:
created_at:
description: CreatedAt holds the value of the "created_at" field.
type: string
description:
description: Description holds the value of the "description" field.
type: string
edges:
$ref: '#/definitions/ent.ItemEdges'
description: |-
Edges holds the relations/edges for other nodes in the graph.
The values are being populated by the ItemQuery when eager-loading is set.
id:
description: ID of the ent.
type: string
manufacturer:
description: Manufacturer holds the value of the "manufacturer" field.
type: string
model_number:
description: ModelNumber holds the value of the "model_number" field.
type: string
name:
description: Name holds the value of the "name" field.
type: string
notes:
description: Notes holds the value of the "notes" field.
type: string
purchase_from:
description: PurchaseFrom holds the value of the "purchase_from" field.
type: string
purchase_price:
description: PurchasePrice holds the value of the "purchase_price" field.
type: number
purchase_receipt_id:
description: PurchaseReceiptID holds the value of the "purchase_receipt_id"
field.
type: string
purchase_time:
description: PurchaseTime holds the value of the "purchase_time" field.
type: string
serial_number:
description: SerialNumber holds the value of the "serial_number" field.
type: string
sold_notes:
description: SoldNotes holds the value of the "sold_notes" field.
type: string
sold_price:
description: SoldPrice holds the value of the "sold_price" field.
type: number
sold_receipt_id:
description: SoldReceiptID holds the value of the "sold_receipt_id" field.
type: string
sold_time:
description: SoldTime holds the value of the "sold_time" field.
type: string
sold_to:
description: SoldTo holds the value of the "sold_to" field.
type: string
updated_at:
description: UpdatedAt holds the value of the "updated_at" field.
type: string
type: object
ent.ItemEdges:
properties:
fields:
description: Fields holds the value of the fields edge.
items:
$ref: '#/definitions/ent.ItemField'
type: array
group:
$ref: '#/definitions/ent.Group'
description: Group holds the value of the group edge.
label:
description: Label holds the value of the label edge.
items:
$ref: '#/definitions/ent.Label'
type: array
location:
$ref: '#/definitions/ent.Location'
description: Location holds the value of the location edge.
type: object
ent.ItemField:
properties:
boolean_value:
description: BooleanValue holds the value of the "boolean_value" field.
type: boolean
created_at:
description: CreatedAt holds the value of the "created_at" field.
type: string
description:
description: Description holds the value of the "description" field.
type: string
edges:
$ref: '#/definitions/ent.ItemFieldEdges'
description: |-
Edges holds the relations/edges for other nodes in the graph.
The values are being populated by the ItemFieldQuery when eager-loading is set.
id:
description: ID of the ent.
type: string
name:
description: Name holds the value of the "name" field.
type: string
number_value:
description: NumberValue holds the value of the "number_value" field.
type: integer
text_value:
description: TextValue holds the value of the "text_value" field.
type: string
time_value:
description: TimeValue holds the value of the "time_value" field.
type: string
type:
description: Type holds the value of the "type" field.
type: string
updated_at:
description: UpdatedAt holds the value of the "updated_at" field.
type: string
type: object
ent.ItemFieldEdges:
properties:
item:
$ref: '#/definitions/ent.Item'
description: Item holds the value of the item edge.
type: object
ent.Label:
properties:
color:
description: Color holds the value of the "color" field.
type: string
created_at:
description: CreatedAt holds the value of the "created_at" field.
type: string
description:
description: Description holds the value of the "description" field.
type: string
edges:
$ref: '#/definitions/ent.LabelEdges'
description: |-
Edges holds the relations/edges for other nodes in the graph.
The values are being populated by the LabelQuery when eager-loading is set.
id:
description: ID of the ent.
type: string
name:
description: Name holds the value of the "name" field.
type: string
updated_at:
description: UpdatedAt holds the value of the "updated_at" field.
type: string
type: object
ent.LabelEdges:
properties:
group:
$ref: '#/definitions/ent.Group'
description: Group holds the value of the group edge.
items:
description: Items holds the value of the items edge.
items:
$ref: '#/definitions/ent.Item'
type: array
type: object
ent.Location:
properties:
created_at:
description: CreatedAt holds the value of the "created_at" field.
type: string
description:
description: Description holds the value of the "description" field.
type: string
edges:
$ref: '#/definitions/ent.LocationEdges'
description: |-
Edges holds the relations/edges for other nodes in the graph.
The values are being populated by the LocationQuery when eager-loading is set.
id:
description: ID of the ent.
type: string
name:
description: Name holds the value of the "name" field.
type: string
updated_at:
description: UpdatedAt holds the value of the "updated_at" field.
type: string
type: object
ent.LocationEdges:
properties:
group:
$ref: '#/definitions/ent.Group'
description: Group holds the value of the group edge.
items:
description: Items holds the value of the items edge.
items:
$ref: '#/definitions/ent.Item'
type: array
type: object
ent.User:
properties:
created_at:
description: CreatedAt holds the value of the "created_at" field.
type: string
edges:
$ref: '#/definitions/ent.UserEdges'
description: |-
Edges holds the relations/edges for other nodes in the graph.
The values are being populated by the UserQuery when eager-loading is set.
email:
description: Email holds the value of the "email" field.
type: string
id:
description: ID of the ent.
type: string
is_superuser:
description: IsSuperuser holds the value of the "is_superuser" field.
type: boolean
name:
description: Name holds the value of the "name" field.
type: string
updated_at:
description: UpdatedAt holds the value of the "updated_at" field.
type: string
type: object
ent.UserEdges:
properties:
auth_tokens:
description: AuthTokens holds the value of the auth_tokens edge.
items:
$ref: '#/definitions/ent.AuthTokens'
type: array
group:
$ref: '#/definitions/ent.Group'
description: Group holds the value of the group edge.
type: object
server.Result:
properties:
details: {}
@ -33,6 +344,8 @@ definitions:
properties:
email:
type: string
groupID:
type: string
isSuperuser:
type: boolean
name:
@ -40,16 +353,21 @@ definitions:
password:
type: string
type: object
types.UserOut:
types.UserIn:
properties:
email:
type: string
id:
type: string
isSuperuser:
type: boolean
name:
type: string
password:
type: string
type: object
types.UserRegistration:
properties:
groupName:
type: string
user:
$ref: '#/definitions/types.UserIn'
type: object
types.UserUpdate:
properties:
@ -99,7 +417,7 @@ paths:
- properties:
item:
items:
$ref: '#/definitions/types.UserOut'
$ref: '#/definitions/ent.User'
type: array
type: object
security:
@ -125,7 +443,7 @@ paths:
- $ref: '#/definitions/server.Result'
- properties:
item:
$ref: '#/definitions/types.UserOut'
$ref: '#/definitions/ent.User'
type: object
security:
- Bearer: []
@ -167,7 +485,7 @@ paths:
- $ref: '#/definitions/server.Result'
- properties:
item:
$ref: '#/definitions/types.UserOut'
$ref: '#/definitions/ent.User'
type: object
security:
- Bearer: []
@ -197,7 +515,7 @@ paths:
- $ref: '#/definitions/server.Result'
- properties:
item:
$ref: '#/definitions/types.UserOut'
$ref: '#/definitions/ent.User'
type: object
security:
- Bearer: []
@ -253,6 +571,30 @@ paths:
summary: User Token Refresh
tags:
- Authentication
/v1/users/register:
post:
parameters:
- description: User Data
in: body
name: payload
required: true
schema:
$ref: '#/definitions/types.UserRegistration'
produces:
- application/json
responses:
"200":
description: OK
schema:
allOf:
- $ref: '#/definitions/server.Result'
- properties:
item:
$ref: '#/definitions/ent.User'
type: object
summary: Get the current user
tags:
- User
/v1/users/self:
get:
produces:
@ -265,7 +607,7 @@ paths:
- $ref: '#/definitions/server.Result'
- properties:
item:
$ref: '#/definitions/types.UserOut'
$ref: '#/definitions/ent.User'
type: object
security:
- Bearer: []

View File

@ -97,7 +97,6 @@ func run(cfg *config.Config) error {
routes := app.newRouter(app.repos)
app.LogRoutes(routes)
app.EnsureAdministrator()
app.SeedDatabase(app.repos)
app.logger.Info("Starting HTTP Server", logger.Props{

View File

@ -64,7 +64,7 @@ func (a *app) mwAuthToken(next http.Handler) http.Handler {
return
}
r = r.WithContext(services.SetUserCtx(r.Context(), &usr, requestToken))
r = r.WithContext(services.SetUserCtx(r.Context(), usr, requestToken))
next.ServeHTTP(w, r)
})

View File

@ -36,26 +36,30 @@ func (a *app) newRouter(repos *repo.AllRepos) *chi.Mux {
// =========================================================================
// API Version 1
v1Base := v1.BaseUrlFunc(prefix)
v1Handlers := v1.NewControllerV1(a.logger, a.services)
r.Post(v1Base("/users/login"), v1Handlers.HandleAuthLogin())
r.Group(func(r chi.Router) {
r.Use(a.mwAuthToken)
r.Get(v1Base("/users/self"), v1Handlers.HandleUserSelf())
r.Put(v1Base("/users/self"), v1Handlers.HandleUserUpdate())
r.Put(v1Base("/users/self/password"), v1Handlers.HandleUserUpdatePassword())
r.Post(v1Base("/users/logout"), v1Handlers.HandleAuthLogout())
r.Get(v1Base("/users/refresh"), v1Handlers.HandleAuthRefresh())
})
r.Group(func(r chi.Router) {
r.Use(a.mwAdminOnly)
r.Get(v1Base("/admin/users"), v1Handlers.HandleAdminUserGetAll())
r.Post(v1Base("/admin/users"), v1Handlers.HandleAdminUserCreate())
r.Get(v1Base("/admin/users/{id}"), v1Handlers.HandleAdminUserGet())
r.Put(v1Base("/admin/users/{id}"), v1Handlers.HandleAdminUserUpdate())
r.Delete(v1Base("/admin/users/{id}"), v1Handlers.HandleAdminUserDelete())
})
v1Base := v1.BaseUrlFunc(prefix)
{
v1Handlers := v1.NewControllerV1(a.logger, a.services)
r.Post(v1Base("/users/register"), v1Handlers.HandleUserRegistration())
r.Post(v1Base("/users/login"), v1Handlers.HandleAuthLogin())
r.Group(func(r chi.Router) {
r.Use(a.mwAuthToken)
r.Get(v1Base("/users/self"), v1Handlers.HandleUserSelf())
r.Put(v1Base("/users/self"), v1Handlers.HandleUserUpdate())
r.Put(v1Base("/users/self/password"), v1Handlers.HandleUserUpdatePassword())
r.Post(v1Base("/users/logout"), v1Handlers.HandleAuthLogout())
r.Get(v1Base("/users/refresh"), v1Handlers.HandleAuthRefresh())
})
r.Group(func(r chi.Router) {
r.Use(a.mwAdminOnly)
r.Get(v1Base("/admin/users"), v1Handlers.HandleAdminUserGetAll())
r.Post(v1Base("/admin/users"), v1Handlers.HandleAdminUserCreate())
r.Get(v1Base("/admin/users/{id}"), v1Handlers.HandleAdminUserGet())
r.Put(v1Base("/admin/users/{id}"), v1Handlers.HandleAdminUserUpdate())
r.Delete(v1Base("/admin/users/{id}"), v1Handlers.HandleAdminUserDelete())
})
}
return r
}

View File

@ -11,6 +11,7 @@ import (
)
const (
DefaultGroup = "Default"
DefaultName = "Admin"
DefaultEmail = "admin@admin.com"
DefaultPassword = "admin"
@ -22,15 +23,13 @@ func (a *app) EnsureAdministrator() {
superusers, err := a.repos.Users.GetSuperusers(context.Background())
if err != nil {
a.logger.Error(err, nil)
a.logger.Fatal(err, nil)
}
if len(superusers) > 0 {
return
}
pw, _ := hasher.HashPassword(DefaultPassword)
newSuperUser := types.UserCreate{
Name: DefaultName,
Email: DefaultEmail,
@ -56,6 +55,11 @@ func (a *app) SeedDatabase(repos *repo.AllRepos) {
return
}
group, err := repos.Groups.Create(context.Background(), DefaultGroup)
if err != nil {
a.logger.Fatal(err, nil)
}
for _, user := range a.conf.Seed.Users {
// Check if User Exists
@ -82,6 +86,7 @@ func (a *app) SeedDatabase(repos *repo.AllRepos) {
Email: user.Email,
IsSuperuser: user.IsSuperuser,
Password: hashedPw,
GroupID: group.ID,
})
if err != nil {

View File

@ -4,13 +4,14 @@ import (
"context"
"testing"
"github.com/hay-kot/content/backend/ent"
"github.com/hay-kot/content/backend/internal/mocks"
"github.com/hay-kot/content/backend/internal/mocks/factories"
"github.com/hay-kot/content/backend/internal/types"
)
var mockHandler = &V1Controller{}
var users = []types.UserOut{}
var users = []*ent.User{}
func userPool() func() {
create := []types.UserCreate{
@ -20,7 +21,7 @@ func userPool() func() {
factories.UserFactory(),
}
userOut := []types.UserOut{}
userOut := []*ent.User{}
for _, user := range create {
usrOut, _ := mockHandler.svc.Admin.Create(context.Background(), user)

View File

@ -17,7 +17,7 @@ import (
// @Summary Gets all users from the database
// @Tags Admin: Users
// @Produce json
// @Success 200 {object} server.Result{item=[]types.UserOut}
// @Success 200 {object} server.Result{item=[]ent.User}
// @Router /v1/admin/users [get]
// @Security Bearer
func (ctrl *V1Controller) HandleAdminUserGetAll() http.HandlerFunc {
@ -38,7 +38,7 @@ func (ctrl *V1Controller) HandleAdminUserGetAll() http.HandlerFunc {
// @Tags Admin: Users
// @Produce json
// @Param id path string true "User ID"
// @Success 200 {object} server.Result{item=types.UserOut}
// @Success 200 {object} server.Result{item=ent.User}
// @Router /v1/admin/users/{id} [get]
// @Security Bearer
func (ctrl *V1Controller) HandleAdminUserGet() http.HandlerFunc {
@ -71,7 +71,7 @@ func (ctrl *V1Controller) HandleAdminUserGet() http.HandlerFunc {
// @Tags Admin: Users
// @Produce json
// @Param payload body types.UserCreate true "User Data"
// @Success 200 {object} server.Result{item=types.UserOut}
// @Success 200 {object} server.Result{item=ent.User}
// @Router /v1/admin/users [POST]
// @Security Bearer
func (ctrl *V1Controller) HandleAdminUserCreate() http.HandlerFunc {
@ -129,7 +129,7 @@ func (ctrl *V1Controller) HandleAdminUserCreate() http.HandlerFunc {
// @Param id path string true "User ID"
// @Param payload body types.UserUpdate true "User Data"
// @Produce json
// @Success 200 {object} server.Result{item=types.UserOut}
// @Success 200 {object} server.Result{item=ent.User}
// @Router /v1/admin/users/{id} [PUT]
// @Security Bearer
func (ctrl *V1Controller) HandleAdminUserUpdate() http.HandlerFunc {

View File

@ -9,9 +9,9 @@ import (
"net/http/httptest"
"testing"
"github.com/hay-kot/content/backend/ent"
"github.com/hay-kot/content/backend/internal/mocks/chimocker"
"github.com/hay-kot/content/backend/internal/mocks/factories"
"github.com/hay-kot/content/backend/internal/types"
"github.com/hay-kot/content/backend/pkgs/server"
"github.com/stretchr/testify/assert"
)
@ -23,11 +23,11 @@ const (
)
type usersResponse struct {
Users []types.UserOut `json:"item"`
Users []*ent.User `json:"item"`
}
type userResponse struct {
User types.UserOut `json:"item"`
User *ent.User `json:"item"`
}
func Test_HandleAdminUserGetAll_Success(t *testing.T) {
@ -37,7 +37,7 @@ func Test_HandleAdminUserGetAll_Success(t *testing.T) {
mockHandler.HandleAdminUserGetAll()(r, req)
response := usersResponse{
Users: []types.UserOut{},
Users: []*ent.User{},
}
_ = json.Unmarshal(r.Body.Bytes(), &response)
@ -68,7 +68,7 @@ func Test_HandleAdminUserGet_Success(t *testing.T) {
assert.Equal(t, http.StatusOK, res.Code)
response := userResponse{
User: types.UserOut{},
User: &ent.User{},
}
_ = json.Unmarshal(res.Body.Bytes(), &response)

View File

@ -4,24 +4,53 @@ import (
"errors"
"net/http"
"github.com/google/uuid"
"github.com/hay-kot/content/backend/internal/services"
"github.com/hay-kot/content/backend/internal/types"
"github.com/hay-kot/content/backend/pkgs/logger"
"github.com/hay-kot/content/backend/pkgs/server"
)
// HandleUserSelf godoc
// @Summary Get the current user
// @Tags User
// @Produce json
// @Param payload body types.UserRegistration true "User Data"
// @Success 200 {object} server.Result{item=ent.User}
// @Router /v1/users/register [Post]
func (ctrl *V1Controller) HandleUserRegistration() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
regData := types.UserRegistration{}
if err := server.Decode(r, &regData); err != nil {
ctrl.log.Error(err, nil)
server.RespondError(w, http.StatusInternalServerError, err)
return
}
usr, err := ctrl.svc.User.RegisterUser(r.Context(), regData)
if err != nil {
ctrl.log.Error(err, nil)
server.RespondError(w, http.StatusInternalServerError, err)
return
}
_ = server.Respond(w, http.StatusOK, server.Wrap(usr))
}
}
// HandleUserSelf godoc
// @Summary Get the current user
// @Tags User
// @Produce json
// @Success 200 {object} server.Result{item=types.UserOut}
// @Success 200 {object} server.Result{item=ent.User}
// @Router /v1/users/self [GET]
// @Security Bearer
func (ctrl *V1Controller) HandleUserSelf() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
token := services.UseTokenCtx(r.Context())
usr, err := ctrl.svc.User.GetSelf(r.Context(), token)
if usr.IsNull() || err != nil {
if usr.ID == uuid.Nil || err != nil {
ctrl.log.Error(errors.New("no user within request context"), nil)
server.RespondInternalServerError(w)
return

View File

@ -4,7 +4,6 @@ import (
"time"
"github.com/google/uuid"
"github.com/hay-kot/content/backend/ent"
"github.com/hay-kot/content/backend/internal/types"
"github.com/hay-kot/content/backend/pkgs/automapper"
"github.com/tkrajina/typescriptify-golang-structs/typescriptify"
@ -12,22 +11,7 @@ import (
// generateMappers serialized the config file into a list of automapper struct
func generateMappers() []automapper.AutoMapper {
return []automapper.AutoMapper{
{
Package: "mapper",
Prefix: "users",
Name: "User Out",
Schema: automapper.Schema{
Type: types.UserOut{},
Prefix: "types",
},
Model: automapper.Model{
Type: ent.User{},
Prefix: "ent",
},
Imports: []string{},
},
}
return []automapper.AutoMapper{}
}
func generateTypeScript() {
@ -43,7 +27,6 @@ func generateTypeScript() {
types.ApiSummary{},
// User Types
types.UserOut{},
types.UserCreate{},
types.UserIn{},
types.UserUpdate{},

View File

@ -20,6 +20,7 @@ mailer:
from: example@email.com
seed:
enabled: true
group: Default
users:
- name: Admin
email: admin@admin.com

View File

@ -53,14 +53,18 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=

View File

@ -10,4 +10,5 @@ type SeedUser struct {
type Seed struct {
Enabled bool `yaml:"enabled" conf:"default:false"`
Users []SeedUser `yaml:"users"`
Group string `yaml:"group"`
}

View File

@ -1,27 +0,0 @@
// Code generated by "/pkgs/automapper"; DO NOT EDIT.
package mapper
import (
"github.com/hay-kot/content/backend/ent"
"github.com/hay-kot/content/backend/internal/types"
)
func UserOutFromModel(from ent.User) types.UserOut {
return types.UserOut{
ID: from.ID,
Name: from.Name,
Email: from.Email,
Password: from.Password,
IsSuperuser: from.IsSuperuser,
}
}
func UserOutToModel(from types.UserOut) ent.User {
return ent.User{
ID: from.ID,
Name: from.Name,
Email: from.Email,
Password: from.Password,
IsSuperuser: from.IsSuperuser,
}
}

View File

@ -0,0 +1,29 @@
package repo
import (
"context"
"github.com/google/uuid"
"github.com/hay-kot/content/backend/ent"
)
type EntGroupRepository struct {
db *ent.Client
}
func (r *EntGroupRepository) Create(ctx context.Context, name string) (*ent.Group, error) {
dbGroup, err := r.db.Group.Create().SetName(name).Save(ctx)
if err != nil {
return dbGroup, err
}
return dbGroup, nil
}
func (r *EntGroupRepository) GetOneId(ctx context.Context, id uuid.UUID) (*ent.Group, error) {
dbGroup, err := r.db.Group.Get(ctx, id)
if err != nil {
return dbGroup, err
}
return dbGroup, nil
}

View File

@ -6,7 +6,6 @@ import (
"github.com/hay-kot/content/backend/ent"
"github.com/hay-kot/content/backend/ent/authtokens"
"github.com/hay-kot/content/backend/internal/mapper"
"github.com/hay-kot/content/backend/internal/types"
)
@ -15,7 +14,7 @@ type EntTokenRepository struct {
}
// GetUserFromToken get's a user from a token
func (r *EntTokenRepository) GetUserFromToken(ctx context.Context, token []byte) (types.UserOut, error) {
func (r *EntTokenRepository) GetUserFromToken(ctx context.Context, token []byte) (*ent.User, error) {
dbToken, err := r.db.AuthTokens.Query().
Where(authtokens.Token(token)).
Where(authtokens.ExpiresAtGTE(time.Now())).
@ -23,10 +22,10 @@ func (r *EntTokenRepository) GetUserFromToken(ctx context.Context, token []byte)
Only(ctx)
if err != nil {
return types.UserOut{}, err
return nil, err
}
return mapper.UserOutFromModel(*dbToken.Edges.User), nil
return dbToken.Edges.User, nil
}
// Creates a token for a user

View File

@ -13,66 +13,41 @@ type EntUserRepository struct {
db *ent.Client
}
func (e *EntUserRepository) toUserOut(usr *types.UserOut, entUsr *ent.User) {
usr.ID = entUsr.ID
usr.Password = entUsr.Password
usr.Name = entUsr.Name
usr.Email = entUsr.Email
usr.IsSuperuser = entUsr.IsSuperuser
}
func (e *EntUserRepository) GetOneId(ctx context.Context, id uuid.UUID) (types.UserOut, error) {
func (e *EntUserRepository) GetOneId(ctx context.Context, id uuid.UUID) (*ent.User, error) {
usr, err := e.db.User.Query().Where(user.ID(id)).Only(ctx)
usrOut := types.UserOut{}
if err != nil {
return usrOut, err
return usr, err
}
e.toUserOut(&usrOut, usr)
return usrOut, nil
return usr, nil
}
func (e *EntUserRepository) GetOneEmail(ctx context.Context, email string) (types.UserOut, error) {
func (e *EntUserRepository) GetOneEmail(ctx context.Context, email string) (*ent.User, error) {
usr, err := e.db.User.Query().Where(user.Email(email)).Only(ctx)
usrOut := types.UserOut{}
if err != nil {
return usrOut, err
return usr, err
}
e.toUserOut(&usrOut, usr)
return usrOut, nil
return usr, nil
}
func (e *EntUserRepository) GetAll(ctx context.Context) ([]types.UserOut, error) {
func (e *EntUserRepository) GetAll(ctx context.Context) ([]*ent.User, error) {
users, err := e.db.User.Query().All(ctx)
if err != nil {
return nil, err
}
var usrs []types.UserOut
for _, usr := range users {
usrOut := types.UserOut{}
e.toUserOut(&usrOut, usr)
usrs = append(usrs, usrOut)
}
return usrs, nil
return users, nil
}
func (e *EntUserRepository) Create(ctx context.Context, usr types.UserCreate) (types.UserOut, error) {
func (e *EntUserRepository) Create(ctx context.Context, usr types.UserCreate) (*ent.User, error) {
err := usr.Validate()
usrOut := types.UserOut{}
if err != nil {
return usrOut, err
return &ent.User{}, err
}
entUser, err := e.db.User.
@ -81,11 +56,10 @@ func (e *EntUserRepository) Create(ctx context.Context, usr types.UserCreate) (t
SetEmail(usr.Email).
SetPassword(usr.Password).
SetIsSuperuser(usr.IsSuperuser).
SetGroupID(usr.GroupID).
Save(ctx)
e.toUserOut(&usrOut, entUser)
return usrOut, err
return entUser, err
}
func (e *EntUserRepository) Update(ctx context.Context, ID uuid.UUID, data types.UserUpdate) error {
@ -122,20 +96,12 @@ func (e *EntUserRepository) DeleteAll(ctx context.Context) error {
return err
}
func (e *EntUserRepository) GetSuperusers(ctx context.Context) ([]types.UserOut, error) {
func (e *EntUserRepository) GetSuperusers(ctx context.Context) ([]*ent.User, error) {
users, err := e.db.User.Query().Where(user.IsSuperuser(true)).All(ctx)
if err != nil {
return nil, err
}
var usrs []types.UserOut
for _, usr := range users {
usrOut := types.UserOut{}
e.toUserOut(&usrOut, usr)
usrs = append(usrs, usrOut)
}
return usrs, nil
return users, nil
}

View File

@ -5,6 +5,7 @@ import (
"fmt"
"testing"
"github.com/hay-kot/content/backend/ent"
"github.com/hay-kot/content/backend/internal/types"
"github.com/hay-kot/content/backend/pkgs/faker"
"github.com/stretchr/testify/assert"
@ -66,7 +67,7 @@ func Test_EntUserRepo_GetAll(t *testing.T) {
ctx := context.Background()
created := []types.UserOut{}
created := []*ent.User{}
for _, usr := range toCreate {
usrOut, _ := testRepos.Users.Create(ctx, usr)

View File

@ -4,13 +4,15 @@ import "github.com/hay-kot/content/backend/ent"
// AllRepos is a container for all the repository interfaces
type AllRepos struct {
Users UserRepository
AuthTokens TokenRepository
Users *EntUserRepository
AuthTokens *EntTokenRepository
Groups *EntGroupRepository
}
func EntAllRepos(db *ent.Client) *AllRepos {
return &AllRepos{
Users: &EntUserRepository{db},
AuthTokens: &EntTokenRepository{db},
Groups: &EntGroupRepository{db},
}
}

View File

@ -1,20 +0,0 @@
package repo
import (
"context"
"github.com/hay-kot/content/backend/internal/types"
)
type TokenRepository interface {
// GetUserFromToken get's a user from a token
GetUserFromToken(ctx context.Context, token []byte) (types.UserOut, error)
// Creates a token for a user
CreateToken(ctx context.Context, createToken types.UserAuthTokenCreate) (types.UserAuthToken, error)
// DeleteToken remove a single token from the database - equivalent to revoke or logout
DeleteToken(ctx context.Context, token []byte) error
// PurgeExpiredTokens removes all expired tokens from the database
PurgeExpiredTokens(ctx context.Context) (int, error)
// DeleteAll removes all tokens from the database
DeleteAll(ctx context.Context) (int, error)
}

View File

@ -1,27 +0,0 @@
package repo
import (
"context"
"github.com/google/uuid"
"github.com/hay-kot/content/backend/internal/types"
)
type UserRepository interface {
// GetOneId returns a user by id
GetOneId(ctx context.Context, ID uuid.UUID) (types.UserOut, error)
// GetOneEmail returns a user by email
GetOneEmail(ctx context.Context, email string) (types.UserOut, error)
// GetAll returns all users
GetAll(ctx context.Context) ([]types.UserOut, error)
// Get Super Users
GetSuperusers(ctx context.Context) ([]types.UserOut, error)
// Create creates a new user
Create(ctx context.Context, user types.UserCreate) (types.UserOut, error)
// Update updates a user
Update(ctx context.Context, ID uuid.UUID, user types.UserUpdate) error
// Delete deletes a user
Delete(ctx context.Context, ID uuid.UUID) error
DeleteAll(ctx context.Context) error
}

View File

@ -3,7 +3,7 @@ package services
import (
"context"
"github.com/hay-kot/content/backend/internal/types"
"github.com/hay-kot/content/backend/ent"
)
type contextKeys struct {
@ -17,16 +17,16 @@ var (
// SetUserCtx is a helper function that sets the ContextUser and ContextUserToken
// values within the context of a web request (or any context).
func SetUserCtx(ctx context.Context, user *types.UserOut, token string) context.Context {
func SetUserCtx(ctx context.Context, user *ent.User, token string) context.Context {
ctx = context.WithValue(ctx, ContextUser, user)
ctx = context.WithValue(ctx, ContextUserToken, token)
return ctx
}
// UseUserCtx is a helper function that returns the user from the context.
func UseUserCtx(ctx context.Context) *types.UserOut {
func UseUserCtx(ctx context.Context) *ent.User {
if val := ctx.Value(ContextUser); val != nil {
return val.(*types.UserOut)
return val.(*ent.User)
}
return nil
}

View File

@ -5,12 +5,12 @@ import (
"testing"
"github.com/google/uuid"
"github.com/hay-kot/content/backend/internal/types"
"github.com/hay-kot/content/backend/ent"
"github.com/stretchr/testify/assert"
)
func Test_SetAuthContext(t *testing.T) {
user := &types.UserOut{
user := &ent.User{
ID: uuid.New(),
}

View File

@ -4,6 +4,7 @@ import (
"context"
"github.com/google/uuid"
"github.com/hay-kot/content/backend/ent"
"github.com/hay-kot/content/backend/internal/repo"
"github.com/hay-kot/content/backend/internal/types"
)
@ -12,27 +13,27 @@ type AdminService struct {
repos *repo.AllRepos
}
func (svc *AdminService) Create(ctx context.Context, usr types.UserCreate) (types.UserOut, error) {
func (svc *AdminService) Create(ctx context.Context, usr types.UserCreate) (*ent.User, error) {
return svc.repos.Users.Create(ctx, usr)
}
func (svc *AdminService) GetAll(ctx context.Context) ([]types.UserOut, error) {
func (svc *AdminService) GetAll(ctx context.Context) ([]*ent.User, error) {
return svc.repos.Users.GetAll(ctx)
}
func (svc *AdminService) GetByID(ctx context.Context, id uuid.UUID) (types.UserOut, error) {
func (svc *AdminService) GetByID(ctx context.Context, id uuid.UUID) (*ent.User, error) {
return svc.repos.Users.GetOneId(ctx, id)
}
func (svc *AdminService) GetByEmail(ctx context.Context, email string) (types.UserOut, error) {
func (svc *AdminService) GetByEmail(ctx context.Context, email string) (*ent.User, error) {
return svc.repos.Users.GetOneEmail(ctx, email)
}
func (svc *AdminService) UpdateProperties(ctx context.Context, ID uuid.UUID, data types.UserUpdate) (types.UserOut, error) {
func (svc *AdminService) UpdateProperties(ctx context.Context, ID uuid.UUID, data types.UserUpdate) (*ent.User, error) {
err := svc.repos.Users.Update(ctx, ID, data)
if err != nil {
return types.UserOut{}, err
return &ent.User{}, err
}
return svc.repos.Users.GetOneId(ctx, ID)

View File

@ -6,6 +6,7 @@ import (
"time"
"github.com/google/uuid"
"github.com/hay-kot/content/backend/ent"
"github.com/hay-kot/content/backend/internal/repo"
"github.com/hay-kot/content/backend/internal/types"
"github.com/hay-kot/content/backend/pkgs/hasher"
@ -22,17 +23,41 @@ type UserService struct {
repos *repo.AllRepos
}
func (svc *UserService) RegisterUser(ctx context.Context, data types.UserRegistration) (*ent.User, error) {
group, err := svc.repos.Groups.Create(ctx, data.GroupName)
if err != nil {
return &ent.User{}, err
}
hashed, _ := hasher.HashPassword(data.User.Password)
usrCreate := types.UserCreate{
Name: data.User.Name,
Email: data.User.Email,
Password: hashed,
IsSuperuser: false,
GroupID: group.ID,
}
usr, err := svc.repos.Users.Create(ctx, usrCreate)
if err != nil {
return &ent.User{}, err
}
return usr, nil
}
// GetSelf returns the user that is currently logged in based of the token provided within
func (svc *UserService) GetSelf(ctx context.Context, requestToken string) (types.UserOut, error) {
func (svc *UserService) GetSelf(ctx context.Context, requestToken string) (*ent.User, error) {
hash := hasher.HashToken(requestToken)
return svc.repos.AuthTokens.GetUserFromToken(ctx, hash)
}
func (svc *UserService) UpdateSelf(ctx context.Context, ID uuid.UUID, data types.UserUpdate) (types.UserOut, error) {
func (svc *UserService) UpdateSelf(ctx context.Context, ID uuid.UUID, data types.UserUpdate) (*ent.User, error) {
err := svc.repos.Users.Update(ctx, ID, data)
if err != nil {
return types.UserOut{}, err
return &ent.User{}, err
}
return svc.repos.Users.GetOneId(ctx, ID)

View File

@ -23,10 +23,11 @@ type UserIn struct {
// in the database. It should to create users from an API unless the user has
// rights to create SuperUsers. For regular user in data use the UserIn struct.
type UserCreate struct {
Name string `json:"name"`
Email string `json:"email"`
Password string `json:"password"`
IsSuperuser bool `json:"isSuperuser"`
Name string `json:"name"`
Email string `json:"email"`
Password string `json:"password"`
IsSuperuser bool `json:"isSuperuser"`
GroupID uuid.UUID `json:"groupID"`
}
func (u *UserCreate) Validate() error {
@ -39,20 +40,12 @@ func (u *UserCreate) Validate() error {
return nil
}
type UserOut struct {
ID uuid.UUID `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
Password string `json:"-"`
IsSuperuser bool `json:"isSuperuser"`
}
// IsNull is a proxy call for `usr.Id == uuid.Nil`
func (usr *UserOut) IsNull() bool {
return usr.ID == uuid.Nil
}
type UserUpdate struct {
Name *string `json:"name"`
Email *string `json:"email"`
}
type UserRegistration struct {
User UserIn `json:"user"`
GroupName string `json:"groupName"`
}

View File

@ -2,9 +2,6 @@ package types
import (
"testing"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
)
func TestUserCreate_Validate(t *testing.T) {
@ -64,13 +61,3 @@ func TestUserCreate_Validate(t *testing.T) {
})
}
}
func TestUserOut_IsNull(t *testing.T) {
nullUser := UserOut{}
assert.True(t, nullUser.IsNull())
nullUser.ID = uuid.New()
assert.False(t, nullUser.IsNull())
}