goserver

package module
v0.0.0-...-601eb82 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 30, 2019 License: MIT Imports: 13 Imported by: 0

README

goserver_example

An exercise in demonstrating simple authentication between client and server.

Usage

The server takes no flags--just make all and run bin/server.

The client has full help output. To see it, run bin/client.

You can also see it all in action by running demo.sh. The expected output is shown in a screenshot below.

Some random notes:

  • Database models following a loose repository pattern (link)
  • Gingko BDD for the database repositories--almost 20% coverage!

Prerequisites

These executables need to be available and generally aren't installed by default on Mac or Linux:

  • go
  • sqlite3

Flaws

These are some of the things that would need to be changed, or otherwise should be changed, before this application would be deployed.

  • Passwords are entered on the client in plaintext
  • Default ServeHTTP handler requires actual endpoints to reparse request bodies
  • Helper function commonality/design (ties into first point)
    • There's a lot of boilerplate in the client functions and endpoints
  • Naming consistencies
  • Server's hardcoded configuration in main.
  • Client should not be configured to read a specific root CA.
  • The http.Client usage in the client should be replaced with an interface (ideally a type that's from a standard Go library) for dependency injection
  • Very limited request format (see next point)
  • Should have used gRPC in hindsight, but this was fun to do from scratch anyway.

Screenshot of Demo

demo working

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type RequestData

type RequestData struct {
	Token    string
	Username string
	Password string
	Error    string
}

RequestData is our general purpose container for data sent between client and server. Different field may be used for different endpoints.

func ParseRequestData

func ParseRequestData(body io.ReadCloser) (*RequestData, error)

ParseRequestData is used to unmarshal data in requests and responses.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is the handle on the main server instance

func NewServer

func NewServer(u UserRepo, s SessionRepo) *Server

NewServer correctly instantiates a new server

func (*Server) Init

func (s *Server) Init()

Init sets up http endpoints

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request)

Handle enables our server to receive requests and route them as we see fit

type Session

type Session struct {
	ID      int    `db:"id"`
	UserID  int    `db:"userid"`
	Token   string `db:"token"`
	Origin  string `db:"origin"`
	Expires string `db:"expires"` // time of expiration in string form
}

Session reflects a session entry in the database

type SessionRepo

type SessionRepo interface {
	Create(s *Session) error
	DeleteByToken(s *Session) error
	GetByID(s *Session) error
	GetByToken(s *Session) error
}

SessionRepo defines the basic interface for managing authentication sessions

type SessionRepoSqlite3

type SessionRepoSqlite3 struct {
	// contains filtered or unexported fields
}

SessionRepoSqlite3 fulfills SessionRepo using a Sqlite3 database

func NewSessionRepoSqlite3

func NewSessionRepoSqlite3(db *sqlx.DB) (*SessionRepoSqlite3, error)

NewSessionRepoSqlite3 prepares a repo given a sqlite db handle

func (*SessionRepoSqlite3) Create

func (repo *SessionRepoSqlite3) Create(s *Session) error

Create tries to insert a session and fills in the ID of the provided Session struct

func (*SessionRepoSqlite3) DeleteByToken

func (repo *SessionRepoSqlite3) DeleteByToken(s *Session) (err error)

Delete deletes the given session using the ID field

func (*SessionRepoSqlite3) GetByID

func (repo *SessionRepoSqlite3) GetByID(s *Session) (err error)

GetByID fills the passed Session struct's fields using the ID field, which must be filled in

func (*SessionRepoSqlite3) GetByToken

func (repo *SessionRepoSqlite3) GetByToken(s *Session) (err error)

GetByID fills the passed Session struct's fields using the ID field, which must be filled in

type ShoeClient

type ShoeClient struct {
	// contains filtered or unexported fields
}

ShoeClient is a convenience wrapper around http.Client

func NewShoeClient

func NewShoeClient(host string, CA []byte, skipVerify bool) *ShoeClient

NewShoeClient configures a ShoeClient for communicating with a ShoeServer

func (*ShoeClient) Authenticate

func (c *ShoeClient) Authenticate(username, password string) (string, error)

func (*ShoeClient) ChangePasswd

func (c *ShoeClient) ChangePasswd(username, password, token string) (err error)

func (*ShoeClient) CreateUser

func (c *ShoeClient) CreateUser(username, password string) (err error)

func (*ShoeClient) Logout

func (c *ShoeClient) Logout(token string) error

func (*ShoeClient) Request

func (c *ShoeClient) Request(endpoint string, data *RequestData) (*http.Response, error)

RequestSecret requests secrets from a ShoeServer

func (*ShoeClient) RequestSecret

func (c *ShoeClient) RequestSecret() (string, error)

RequestSecret requests secrets from a ShoeServer

type User

type User struct {
	ID       int    `db:"id"`
	Username string `db:"username"`
	Password string `db:"password"`
	Salt     string `db:"salt"`
}

User reflects a user entry in the database This implementation doesn't actually use the salt field because of the bcrypt package provided by Go.

type UserRepo

type UserRepo interface {
	CreateUser(user *User) error
	UpdateUserPasswd(user *User) error
	GetUserByID(user *User) error
	GetUserByUsername(user *User) error
}

UserRepo is a general interface definition for getting persistent user data

type UserRepoSqlite3

type UserRepoSqlite3 struct {
	// contains filtered or unexported fields
}

UserRepoSqlite3 fulfills UserRepo using a Sqlite3 database

func NewUserRepoSqlite3

func NewUserRepoSqlite3(db *sqlx.DB) (*UserRepoSqlite3, error)

NewUserRepoSqlite3 prepares a repo given a sqlite db handle

func (*UserRepoSqlite3) CreateUser

func (repo *UserRepoSqlite3) CreateUser(s *User) error

CreateUser tries to insert a user and fills in the ID of the provided user

func (*UserRepoSqlite3) GetUserByID

func (repo *UserRepoSqlite3) GetUserByID(s *User) (err error)

GetUserByID fills the passed User struct's fields using the ID field, which must be filled in

func (*UserRepoSqlite3) GetUserByUsername

func (repo *UserRepoSqlite3) GetUserByUsername(s *User) (err error)

GetUserByUsername fills the passed User struct's fields using the username field, which must be filled in

func (*UserRepoSqlite3) UpdateUserPasswd

func (repo *UserRepoSqlite3) UpdateUserPasswd(s *User) (err error)

UpdateUserPasswd attempts to update the given user's corresponding password and salt

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL