folder structure refactor volgens doc

This commit is contained in:
darius 2024-05-15 15:27:18 +02:00
parent c2f4ae10e8
commit 7e8788f7f8
80 changed files with 483 additions and 52 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
/.env
/api/.env

1
.idea/vcs.xml generated
View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/../portfolio-backend" vcs="Git" />
</component>
</project>

View File

@ -4,7 +4,7 @@ FROM golang:latest
# Set the working directory to /app
WORKDIR .
# Copy the current directory contents into the container at /app
COPY . .
COPY .. .
# Download and install any required dependencies
RUN go mod download

View File

@ -11,4 +11,5 @@ func ApiRoutes(mux **http.ServeMux) {
m.HandleFunc("/api/", handler.CatchAllHandler)
m.HandleFunc("POST /api/user", handler.CreateUser)
m.HandleFunc("GET /api/user/{id}", handler.GetUser)
m.HandleFunc("POST /api/login", handler.Login)
}

View File

@ -0,0 +1,51 @@
package handler
import (
"context"
"encoding/json"
"fmt"
"net/http"
"portfolio/database/ent"
"portfolio/database/ent/user"
"portfolio/database/query"
"portfolio/service/bcrypt"
)
func Login(w http.ResponseWriter, r *http.Request) {
fmt.Println("test")
var u *ent.User
isHtmx := r.Header.Get("HX-Request")
if isHtmx == "true" {
u = &ent.User{
Name: r.PostFormValue("name"),
Password: r.PostFormValue("password"),
Role: user.Role(r.PostFormValue("role")),
}
} else {
err := json.NewDecoder(r.Body).Decode(&u)
if err != nil {
InternalServerErrorHandler(w)
}
}
User, err := query.GetLogin(context.Background(), u.Name)
if err != nil {
return
}
if bcrypt.CheckPasswordHash(u.Password, User.Password) {
w.Header().Set("HX-Location", "/")
return
} else {
}
w.Header().Set("Content-Type", "application/json")
err = json.NewEncoder(w).Encode(User)
if err != nil {
return
}
}

View File

@ -0,0 +1,24 @@
package webHandler
import (
"html/template"
"net/http"
)
func InitLoginpage(w http.ResponseWriter, r *http.Request) {
tmpl := template.Must(template.ParseFiles(
"./templates/login/index.html",
"./templates/navbar/index.html",
"./templates/themeSelector/index.html",
))
err := tmpl.Execute(w, nil)
if err != nil {
_, err := w.Write([]byte("failed to load"))
if err != nil {
return
}
return
}
}

View File

@ -11,6 +11,7 @@ func WebRoutes(mux **http.ServeMux) {
m.HandleFunc("GET /{$}", webHandler.InitHomepage)
m.HandleFunc("GET /projecten/{$}", webHandler.InitProjectpage)
m.HandleFunc("GET /about/{$}", webHandler.InitAboutpage)
m.HandleFunc("GET /login/{$}", webHandler.InitLoginpage)
m.HandleFunc("POST /theme", webHandler.UpdateTheme)

View File

@ -42,7 +42,8 @@ var (
// UsersColumns holds the columns for the "users" table.
UsersColumns = []*schema.Column{
{Name: "id", Type: field.TypeInt, Increment: true},
{Name: "name", Type: field.TypeString, Default: "John doe"},
{Name: "name", Type: field.TypeString, Unique: true},
{Name: "password", Type: field.TypeString},
{Name: "role", Type: field.TypeEnum, Enums: []string{"admin", "user", "visitor"}},
}
// UsersTable holds the schema information for the "users" table.

View File

@ -932,6 +932,7 @@ type UserMutation struct {
typ string
id *int
name *string
password *string
role *user.Role
clearedFields map[string]struct{}
teams map[int]struct{}
@ -1076,6 +1077,42 @@ func (m *UserMutation) ResetName() {
m.name = nil
}
// SetPassword sets the "password" field.
func (m *UserMutation) SetPassword(s string) {
m.password = &s
}
// Password returns the value of the "password" field in the mutation.
func (m *UserMutation) Password() (r string, exists bool) {
v := m.password
if v == nil {
return
}
return *v, true
}
// OldPassword returns the old "password" field's value of the User entity.
// If the User object wasn't provided to the builder, the object is fetched from the database.
// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
func (m *UserMutation) OldPassword(ctx context.Context) (v string, err error) {
if !m.op.Is(OpUpdateOne) {
return v, errors.New("OldPassword is only allowed on UpdateOne operations")
}
if m.id == nil || m.oldValue == nil {
return v, errors.New("OldPassword requires an ID field in the mutation")
}
oldValue, err := m.oldValue(ctx)
if err != nil {
return v, fmt.Errorf("querying old value for OldPassword: %w", err)
}
return oldValue.Password, nil
}
// ResetPassword resets all changes to the "password" field.
func (m *UserMutation) ResetPassword() {
m.password = nil
}
// SetRole sets the "role" field.
func (m *UserMutation) SetRole(u user.Role) {
m.role = &u
@ -1200,10 +1237,13 @@ func (m *UserMutation) Type() string {
// order to get all numeric fields that were incremented/decremented, call
// AddedFields().
func (m *UserMutation) Fields() []string {
fields := make([]string, 0, 2)
fields := make([]string, 0, 3)
if m.name != nil {
fields = append(fields, user.FieldName)
}
if m.password != nil {
fields = append(fields, user.FieldPassword)
}
if m.role != nil {
fields = append(fields, user.FieldRole)
}
@ -1217,6 +1257,8 @@ func (m *UserMutation) Field(name string) (ent.Value, bool) {
switch name {
case user.FieldName:
return m.Name()
case user.FieldPassword:
return m.Password()
case user.FieldRole:
return m.Role()
}
@ -1230,6 +1272,8 @@ func (m *UserMutation) OldField(ctx context.Context, name string) (ent.Value, er
switch name {
case user.FieldName:
return m.OldName(ctx)
case user.FieldPassword:
return m.OldPassword(ctx)
case user.FieldRole:
return m.OldRole(ctx)
}
@ -1248,6 +1292,13 @@ func (m *UserMutation) SetField(name string, value ent.Value) error {
}
m.SetName(v)
return nil
case user.FieldPassword:
v, ok := value.(string)
if !ok {
return fmt.Errorf("unexpected type %T for field %s", value, name)
}
m.SetPassword(v)
return nil
case user.FieldRole:
v, ok := value.(user.Role)
if !ok {
@ -1307,6 +1358,9 @@ func (m *UserMutation) ResetField(name string) error {
case user.FieldName:
m.ResetName()
return nil
case user.FieldPassword:
m.ResetPassword()
return nil
case user.FieldRole:
m.ResetRole()
return nil

View File

@ -0,0 +1,9 @@
// Code generated by ent, DO NOT EDIT.
package ent
// The init function reads all schema descriptors with runtime code
// (default values, validators, hooks and policies) and stitches it
// to their package variables.
func init() {
}

View File

@ -15,7 +15,8 @@ type User struct {
func (User) Fields() []ent.Field {
return []ent.Field{
field.String("name").
Default("John doe"),
Unique(),
field.String("password"),
field.Enum("role").
Values("admin", "user", "visitor"),
}

View File

@ -18,6 +18,8 @@ type User struct {
ID int `json:"id,omitempty"`
// Name holds the value of the "name" field.
Name string `json:"name,omitempty"`
// Password holds the value of the "password" field.
Password string `json:"password,omitempty"`
// Role holds the value of the "role" field.
Role user.Role `json:"role,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
@ -51,7 +53,7 @@ func (*User) scanValues(columns []string) ([]any, error) {
switch columns[i] {
case user.FieldID:
values[i] = new(sql.NullInt64)
case user.FieldName, user.FieldRole:
case user.FieldName, user.FieldPassword, user.FieldRole:
values[i] = new(sql.NullString)
default:
values[i] = new(sql.UnknownType)
@ -80,6 +82,12 @@ func (u *User) assignValues(columns []string, values []any) error {
} else if value.Valid {
u.Name = value.String
}
case user.FieldPassword:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field password", values[i])
} else if value.Valid {
u.Password = value.String
}
case user.FieldRole:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field role", values[i])
@ -130,6 +138,9 @@ func (u *User) String() string {
builder.WriteString("name=")
builder.WriteString(u.Name)
builder.WriteString(", ")
builder.WriteString("password=")
builder.WriteString(u.Password)
builder.WriteString(", ")
builder.WriteString("role=")
builder.WriteString(fmt.Sprintf("%v", u.Role))
builder.WriteByte(')')

View File

@ -16,6 +16,8 @@ const (
FieldID = "id"
// FieldName holds the string denoting the name field in the database.
FieldName = "name"
// FieldPassword holds the string denoting the password field in the database.
FieldPassword = "password"
// FieldRole holds the string denoting the role field in the database.
FieldRole = "role"
// EdgeTeams holds the string denoting the teams edge name in mutations.
@ -33,6 +35,7 @@ const (
var Columns = []string{
FieldID,
FieldName,
FieldPassword,
FieldRole,
}
@ -52,11 +55,6 @@ func ValidColumn(column string) bool {
return false
}
var (
// DefaultName holds the default value on creation for the "name" field.
DefaultName string
)
// Role defines the type for the "role" enum field.
type Role string
@ -94,6 +92,11 @@ func ByName(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldName, opts...).ToFunc()
}
// ByPassword orders the results by the password field.
func ByPassword(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldPassword, opts...).ToFunc()
}
// ByRole orders the results by the role field.
func ByRole(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldRole, opts...).ToFunc()

View File

@ -59,6 +59,11 @@ func Name(v string) predicate.User {
return predicate.User(sql.FieldEQ(FieldName, v))
}
// Password applies equality check predicate on the "password" field. It's identical to PasswordEQ.
func Password(v string) predicate.User {
return predicate.User(sql.FieldEQ(FieldPassword, v))
}
// NameEQ applies the EQ predicate on the "name" field.
func NameEQ(v string) predicate.User {
return predicate.User(sql.FieldEQ(FieldName, v))
@ -124,6 +129,71 @@ func NameContainsFold(v string) predicate.User {
return predicate.User(sql.FieldContainsFold(FieldName, v))
}
// PasswordEQ applies the EQ predicate on the "password" field.
func PasswordEQ(v string) predicate.User {
return predicate.User(sql.FieldEQ(FieldPassword, v))
}
// PasswordNEQ applies the NEQ predicate on the "password" field.
func PasswordNEQ(v string) predicate.User {
return predicate.User(sql.FieldNEQ(FieldPassword, v))
}
// PasswordIn applies the In predicate on the "password" field.
func PasswordIn(vs ...string) predicate.User {
return predicate.User(sql.FieldIn(FieldPassword, vs...))
}
// PasswordNotIn applies the NotIn predicate on the "password" field.
func PasswordNotIn(vs ...string) predicate.User {
return predicate.User(sql.FieldNotIn(FieldPassword, vs...))
}
// PasswordGT applies the GT predicate on the "password" field.
func PasswordGT(v string) predicate.User {
return predicate.User(sql.FieldGT(FieldPassword, v))
}
// PasswordGTE applies the GTE predicate on the "password" field.
func PasswordGTE(v string) predicate.User {
return predicate.User(sql.FieldGTE(FieldPassword, v))
}
// PasswordLT applies the LT predicate on the "password" field.
func PasswordLT(v string) predicate.User {
return predicate.User(sql.FieldLT(FieldPassword, v))
}
// PasswordLTE applies the LTE predicate on the "password" field.
func PasswordLTE(v string) predicate.User {
return predicate.User(sql.FieldLTE(FieldPassword, v))
}
// PasswordContains applies the Contains predicate on the "password" field.
func PasswordContains(v string) predicate.User {
return predicate.User(sql.FieldContains(FieldPassword, v))
}
// PasswordHasPrefix applies the HasPrefix predicate on the "password" field.
func PasswordHasPrefix(v string) predicate.User {
return predicate.User(sql.FieldHasPrefix(FieldPassword, v))
}
// PasswordHasSuffix applies the HasSuffix predicate on the "password" field.
func PasswordHasSuffix(v string) predicate.User {
return predicate.User(sql.FieldHasSuffix(FieldPassword, v))
}
// PasswordEqualFold applies the EqualFold predicate on the "password" field.
func PasswordEqualFold(v string) predicate.User {
return predicate.User(sql.FieldEqualFold(FieldPassword, v))
}
// PasswordContainsFold applies the ContainsFold predicate on the "password" field.
func PasswordContainsFold(v string) predicate.User {
return predicate.User(sql.FieldContainsFold(FieldPassword, v))
}
// RoleEQ applies the EQ predicate on the "role" field.
func RoleEQ(v Role) predicate.User {
return predicate.User(sql.FieldEQ(FieldRole, v))

View File

@ -26,11 +26,9 @@ func (uc *UserCreate) SetName(s string) *UserCreate {
return uc
}
// SetNillableName sets the "name" field if the given value is not nil.
func (uc *UserCreate) SetNillableName(s *string) *UserCreate {
if s != nil {
uc.SetName(*s)
}
// SetPassword sets the "password" field.
func (uc *UserCreate) SetPassword(s string) *UserCreate {
uc.mutation.SetPassword(s)
return uc
}
@ -62,7 +60,6 @@ func (uc *UserCreate) Mutation() *UserMutation {
// Save creates the User in the database.
func (uc *UserCreate) Save(ctx context.Context) (*User, error) {
uc.defaults()
return withHooks(ctx, uc.sqlSave, uc.mutation, uc.hooks)
}
@ -88,19 +85,14 @@ func (uc *UserCreate) ExecX(ctx context.Context) {
}
}
// defaults sets the default values of the builder before save.
func (uc *UserCreate) defaults() {
if _, ok := uc.mutation.Name(); !ok {
v := user.DefaultName
uc.mutation.SetName(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (uc *UserCreate) check() error {
if _, ok := uc.mutation.Name(); !ok {
return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "User.name"`)}
}
if _, ok := uc.mutation.Password(); !ok {
return &ValidationError{Name: "password", err: errors.New(`ent: missing required field "User.password"`)}
}
if _, ok := uc.mutation.Role(); !ok {
return &ValidationError{Name: "role", err: errors.New(`ent: missing required field "User.role"`)}
}
@ -139,6 +131,10 @@ func (uc *UserCreate) createSpec() (*User, *sqlgraph.CreateSpec) {
_spec.SetField(user.FieldName, field.TypeString, value)
_node.Name = value
}
if value, ok := uc.mutation.Password(); ok {
_spec.SetField(user.FieldPassword, field.TypeString, value)
_node.Password = value
}
if value, ok := uc.mutation.Role(); ok {
_spec.SetField(user.FieldRole, field.TypeEnum, value)
_node.Role = value
@ -180,7 +176,6 @@ func (ucb *UserCreateBulk) Save(ctx context.Context) ([]*User, error) {
for i := range ucb.builders {
func(i int, root context.Context) {
builder := ucb.builders[i]
builder.defaults()
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
mutation, ok := m.(*UserMutation)
if !ok {

View File

@ -42,6 +42,20 @@ func (uu *UserUpdate) SetNillableName(s *string) *UserUpdate {
return uu
}
// SetPassword sets the "password" field.
func (uu *UserUpdate) SetPassword(s string) *UserUpdate {
uu.mutation.SetPassword(s)
return uu
}
// SetNillablePassword sets the "password" field if the given value is not nil.
func (uu *UserUpdate) SetNillablePassword(s *string) *UserUpdate {
if s != nil {
uu.SetPassword(*s)
}
return uu
}
// SetRole sets the "role" field.
func (uu *UserUpdate) SetRole(u user.Role) *UserUpdate {
uu.mutation.SetRole(u)
@ -149,6 +163,9 @@ func (uu *UserUpdate) sqlSave(ctx context.Context) (n int, err error) {
if value, ok := uu.mutation.Name(); ok {
_spec.SetField(user.FieldName, field.TypeString, value)
}
if value, ok := uu.mutation.Password(); ok {
_spec.SetField(user.FieldPassword, field.TypeString, value)
}
if value, ok := uu.mutation.Role(); ok {
_spec.SetField(user.FieldRole, field.TypeEnum, value)
}
@ -231,6 +248,20 @@ func (uuo *UserUpdateOne) SetNillableName(s *string) *UserUpdateOne {
return uuo
}
// SetPassword sets the "password" field.
func (uuo *UserUpdateOne) SetPassword(s string) *UserUpdateOne {
uuo.mutation.SetPassword(s)
return uuo
}
// SetNillablePassword sets the "password" field if the given value is not nil.
func (uuo *UserUpdateOne) SetNillablePassword(s *string) *UserUpdateOne {
if s != nil {
uuo.SetPassword(*s)
}
return uuo
}
// SetRole sets the "role" field.
func (uuo *UserUpdateOne) SetRole(u user.Role) *UserUpdateOne {
uuo.mutation.SetRole(u)
@ -368,6 +399,9 @@ func (uuo *UserUpdateOne) sqlSave(ctx context.Context) (_node *User, err error)
if value, ok := uuo.mutation.Name(); ok {
_spec.SetField(user.FieldName, field.TypeString, value)
}
if value, ok := uuo.mutation.Password(); ok {
_spec.SetField(user.FieldPassword, field.TypeString, value)
}
if value, ok := uuo.mutation.Role(); ok {
_spec.SetField(user.FieldRole, field.TypeEnum, value)
}

View File

@ -0,0 +1,23 @@
package query
import (
"context"
"fmt"
"log"
"portfolio/database"
"portfolio/database/ent"
"portfolio/database/ent/user"
)
func GetLogin(ctx context.Context, name string) (*ent.User, error) {
u, err := database.Client.User.
Query().
Where(user.Name(name)).
Only(ctx)
if err != nil {
return nil, fmt.Errorf("failed querying user: %w", err)
}
log.Println("user returned: ", u)
return u, nil
}

View File

@ -19,6 +19,7 @@ require (
github.com/hashicorp/hcl/v2 v2.19.1 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/zclconf/go-cty v1.14.2 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/mod v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
)

View File

@ -58,6 +58,8 @@ github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/zclconf/go-cty v1.14.2 h1:kTG7lqmBou0Zkx35r6HJHUQTvaRPr5bIAf3AoHS0izI=
github.com/zclconf/go-cty v1.14.2/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=

View File

@ -15,7 +15,7 @@ func main() {
log.Fatalf(".env not found: %v", err)
return
}
print("test")
// Create a new request multiplexer
// Take incoming requests and dispatch them to the matching webHandler
mux := http.NewServeMux()

View File

@ -0,0 +1,15 @@
package bcrypt
import "golang.org/x/crypto/bcrypt"
func HashPassword(password string) (string, error) {
//generate hash from password
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
return string(bytes), err
}
func CheckPasswordHash(password, hash string) bool {
//check password with hash
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err == nil
}

View File

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

Before

Width:  |  Height:  |  Size: 1007 B

After

Width:  |  Height:  |  Size: 1007 B

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,157 @@
<!doctype html>
<html lang="en" data-bs-theme="auto">
<head><script src="../assets/js/color-modes.js"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
<meta name="generator" content="Hugo 0.122.0">
<title>Signin Template · Bootstrap v5.3</title>
<link rel="canonical" href="https://getbootstrap.com/docs/5.3/examples/sign-in/">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@docsearch/css@3">
<link href="../assets/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
@media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
.b-example-divider {
width: 100%;
height: 3rem;
background-color: rgba(0, 0, 0, .1);
border: solid rgba(0, 0, 0, .15);
border-width: 1px 0;
box-shadow: inset 0 .5em 1.5em rgba(0, 0, 0, .1), inset 0 .125em .5em rgba(0, 0, 0, .15);
}
.b-example-vr {
flex-shrink: 0;
width: 1.5rem;
height: 100vh;
}
.bi {
vertical-align: -.125em;
fill: currentColor;
}
.nav-scroller {
position: relative;
z-index: 2;
height: 2.75rem;
overflow-y: hidden;
}
.nav-scroller .nav {
display: flex;
flex-wrap: nowrap;
padding-bottom: 1rem;
margin-top: -1px;
overflow-x: auto;
text-align: center;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
}
.btn-bd-primary {
--bd-violet-bg: #712cf9;
--bd-violet-rgb: 112.520718, 44.062154, 249.437846;
--bs-btn-font-weight: 600;
--bs-btn-color: var(--bs-white);
--bs-btn-bg: var(--bd-violet-bg);
--bs-btn-border-color: var(--bd-violet-bg);
--bs-btn-hover-color: var(--bs-white);
--bs-btn-hover-bg: #6528e0;
--bs-btn-hover-border-color: #6528e0;
--bs-btn-focus-shadow-rgb: var(--bd-violet-rgb);
--bs-btn-active-color: var(--bs-btn-hover-color);
--bs-btn-active-bg: #5a23c8;
--bs-btn-active-border-color: #5a23c8;
}
.bd-mode-toggle {
z-index: 1500;
}
.bd-mode-toggle .dropdown-menu .active .bi {
display: block !important;
}
body {
height: 100%;
}
.form-signin {
max-width: 330px;
padding: 1rem;
}
.form-signin .form-floating:focus-within {
z-index: 2;
}
.form-signin input[type="email"] {
margin-bottom: -1px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
}
.form-signin input[type="password"] {
margin-bottom: 10px;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
</style>
</head>
<body class="d-flex align-items-center py-4 bg-body-tertiary">
{{template "themeSelector"}}
<main class="form-signin w-100 m-auto">
<form hx-post="/api/login" hx-target="body">
<img class="mb-4" src="../assets/brand/bootstrap-logo.svg" alt="" width="72" height="57">
<h1 class="h3 mb-3 fw-normal">Please sign in</h1>
<div class="form-floating">
<input type="email" class="form-control" name="name" id="floatingInput" placeholder="name@example.com">
<label for="floatingInput">Naam</label>
</div>
<div class="form-floating">
<input type="password" class="form-control" name="password" id="floatingPassword" placeholder="Password">
<label for="floatingPassword">Password</label>
</div>
<div class="form-check text-start my-3">
<input class="form-check-input" type="checkbox" value="remember-me" id="flexCheckDefault">
<label class="form-check-label" for="flexCheckDefault">
Remember me
</label>
</div>
<button class="btn btn-primary w-100 py-2" type="submit">Sign in</button>
<p class="mt-5 mb-3 text-body-secondary">&copy; 20172024</p>
</form>
</main>
<script src="../assets/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@ -20,10 +20,7 @@
<a class="nav-link disabled" aria-disabled="true">Servers</a>
</li>
</ul>
<form class="d-flex" role="search">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
<a class="btn btn-primary" href="/login">Login</a>
</div>
</div>
</nav>

View File

@ -1,20 +0,0 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"portfolio/database/ent/schema"
"portfolio/database/ent/user"
)
// The init function reads all schema descriptors with runtime code
// (default values, validators, hooks and policies) and stitches it
// to their package variables.
func init() {
userFields := schema.User{}.Fields()
_ = userFields
// userDescName is the schema descriptor for name field.
userDescName := userFields[0].Descriptor()
// user.DefaultName holds the default value on creation for the name field.
user.DefaultName = userDescName.Default.(string)
}

View File

@ -2,7 +2,7 @@ version: '3.8'
services:
api:
build: .
build: ./api
ports:
- "4002:4002"
restart: unless-stopped