Compare commits
3 Commits
b379b7a5af
...
b29520c5af
| Author | SHA1 | Date | |
|---|---|---|---|
|
b29520c5af
|
|||
|
007e61bca1
|
|||
|
92ddff0917
|
@@ -2,12 +2,20 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"git.dubyatp.xyz/dubyatp/scannerbot/server/db"
|
"git.dubyatp.xyz/dubyatp/scannerbot/server/db"
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
|
"github.com/go-chi/cors"
|
||||||
|
"github.com/go-chi/docgen"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var routes = flag.Bool("routes", false, "Generate API route documentation")
|
||||||
|
|
||||||
func Start() {
|
func Start() {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
db.InitPostgres(ctx)
|
db.InitPostgres(ctx)
|
||||||
@@ -17,6 +25,15 @@ func Start() {
|
|||||||
|
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
|
|
||||||
|
r.Use(cors.Handler(cors.Options{
|
||||||
|
AllowedOrigins: strings.Split(os.Getenv("ALLOWED_ORIGINS"), ","),
|
||||||
|
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
|
||||||
|
AllowedHeaders: []string{"Accept", "Authorization", "Content-Type", "X-CSRF-Token"},
|
||||||
|
ExposedHeaders: []string{"Link"},
|
||||||
|
AllowCredentials: true,
|
||||||
|
MaxAge: 300, // preflight request cache
|
||||||
|
}))
|
||||||
|
|
||||||
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Write([]byte("hello world"))
|
w.Write([]byte("hello world"))
|
||||||
})
|
})
|
||||||
@@ -76,5 +93,13 @@ func Start() {
|
|||||||
r.Post("/", NewUser)
|
r.Post("/", NewUser)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if *routes {
|
||||||
|
fmt.Println(docgen.MarkdownRoutesDoc(r, docgen.MarkdownOpts{
|
||||||
|
ProjectPath: "git.dubyatp.xyz/williamp/scannerbot",
|
||||||
|
Intro: "ScannerBot Server API routes",
|
||||||
|
}))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
http.ListenAndServe(":3000", r)
|
http.ListenAndServe(":3000", r)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/ajg/form v1.5.1 // indirect
|
github.com/ajg/form v1.5.1 // indirect
|
||||||
|
github.com/go-chi/cors v1.2.2 // indirect
|
||||||
|
github.com/go-chi/docgen v1.4.0 // indirect
|
||||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||||
|
|||||||
@@ -3,8 +3,14 @@ github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||||
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
|
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
|
||||||
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
||||||
|
github.com/go-chi/cors v1.2.2 h1:Jmey33TE+b+rB7fT8MUy1u0I4L+NARQlK6LhzKPSyQE=
|
||||||
|
github.com/go-chi/cors v1.2.2/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||||
|
github.com/go-chi/docgen v1.4.0 h1:0h3Cmw6VGR5WhYUaQA+xVdKVO/WzD/ANiSp5AaPluRQ=
|
||||||
|
github.com/go-chi/docgen v1.4.0/go.mod h1:G9W0G551cs2BFMSn/cnGwX+JBHEloAgo17MBhyrnhPI=
|
||||||
|
github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns=
|
||||||
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
|
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
|
||||||
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||||
@@ -45,6 +51,7 @@ google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zN
|
|||||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
+4
-1
@@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
@@ -10,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var REQUIRED_ENVS = [...]string{
|
var REQUIRED_ENVS = [...]string{
|
||||||
"DATABASE_URL", "JWT_SECRET", "FILE_BACKEND",
|
"DATABASE_URL", "JWT_SECRET", "FILE_BACKEND", "ALLOWED_ORIGINS",
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkEnvVars(keys []string) (bool, []string) {
|
func checkEnvVars(keys []string) (bool, []string) {
|
||||||
@@ -25,6 +26,8 @@ func checkEnvVars(keys []string) (bool, []string) {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
err := godotenv.Load()
|
err := godotenv.Load()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Debug("No .env file loaded, will try OS environment variables")
|
slog.Debug("No .env file loaded, will try OS environment variables")
|
||||||
|
|||||||
@@ -0,0 +1,150 @@
|
|||||||
|
# git.dubyatp.xyz/williamp/scannerbot
|
||||||
|
|
||||||
|
ScannerBot Server API routes
|
||||||
|
|
||||||
|
## Routes
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>`/`</summary>
|
||||||
|
|
||||||
|
- [o-chi/cors.(*Cors).Handler-fm]()
|
||||||
|
- **/**
|
||||||
|
- _GET_
|
||||||
|
- [Start.func1]()
|
||||||
|
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>`/channels`</summary>
|
||||||
|
|
||||||
|
- [o-chi/cors.(*Cors).Handler-fm]()
|
||||||
|
- **/channels**
|
||||||
|
- [SessionAuthMiddleware]()
|
||||||
|
- **/**
|
||||||
|
- _GET_
|
||||||
|
- [ListChannels]()
|
||||||
|
- _POST_
|
||||||
|
- [NewChannel]()
|
||||||
|
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>`/channels/{channelID}`</summary>
|
||||||
|
|
||||||
|
- [o-chi/cors.(*Cors).Handler-fm]()
|
||||||
|
- **/channels**
|
||||||
|
- [SessionAuthMiddleware]()
|
||||||
|
- **/{channelID}**
|
||||||
|
- **/**
|
||||||
|
- _DELETE_
|
||||||
|
- [DeleteChannel]()
|
||||||
|
- _GET_
|
||||||
|
- [GetChannel]()
|
||||||
|
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>`/channels/{channelID}/messages`</summary>
|
||||||
|
|
||||||
|
- [o-chi/cors.(*Cors).Handler-fm]()
|
||||||
|
- **/channels**
|
||||||
|
- [SessionAuthMiddleware]()
|
||||||
|
- **/{channelID}**
|
||||||
|
- **/messages**
|
||||||
|
- **/**
|
||||||
|
- _GET_
|
||||||
|
- [ListMessages]()
|
||||||
|
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>`/channels/{channelID}/messages/{messageID}`</summary>
|
||||||
|
|
||||||
|
- [o-chi/cors.(*Cors).Handler-fm]()
|
||||||
|
- **/channels**
|
||||||
|
- [SessionAuthMiddleware]()
|
||||||
|
- **/{channelID}**
|
||||||
|
- **/messages**
|
||||||
|
- **/{messageID}**
|
||||||
|
- **/**
|
||||||
|
- _GET_
|
||||||
|
- [GetMessage]()
|
||||||
|
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>`/files/{fileID}`</summary>
|
||||||
|
|
||||||
|
- [o-chi/cors.(*Cors).Handler-fm]()
|
||||||
|
- **/files**
|
||||||
|
- [SessionAuthMiddleware]()
|
||||||
|
- **/{fileID}**
|
||||||
|
- **/**
|
||||||
|
- _GET_
|
||||||
|
- [ServeFile]()
|
||||||
|
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>`/login`</summary>
|
||||||
|
|
||||||
|
- [o-chi/cors.(*Cors).Handler-fm]()
|
||||||
|
- **/login**
|
||||||
|
- **/**
|
||||||
|
- _POST_
|
||||||
|
- [Login]()
|
||||||
|
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>`/logout`</summary>
|
||||||
|
|
||||||
|
- [o-chi/cors.(*Cors).Handler-fm]()
|
||||||
|
- **/logout**
|
||||||
|
- [SessionAuthMiddleware]()
|
||||||
|
- **/**
|
||||||
|
- _POST_
|
||||||
|
- [Logout]()
|
||||||
|
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>`/register`</summary>
|
||||||
|
|
||||||
|
- [o-chi/cors.(*Cors).Handler-fm]()
|
||||||
|
- **/register**
|
||||||
|
- **/**
|
||||||
|
- _POST_
|
||||||
|
- [NewUser]()
|
||||||
|
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>`/users`</summary>
|
||||||
|
|
||||||
|
- [o-chi/cors.(*Cors).Handler-fm]()
|
||||||
|
- **/users**
|
||||||
|
- [SessionAuthMiddleware]()
|
||||||
|
- **/**
|
||||||
|
- _GET_
|
||||||
|
- [ListUsers]()
|
||||||
|
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>`/users/{userID}`</summary>
|
||||||
|
|
||||||
|
- [o-chi/cors.(*Cors).Handler-fm]()
|
||||||
|
- **/users**
|
||||||
|
- [SessionAuthMiddleware]()
|
||||||
|
- **/{userID}**
|
||||||
|
- **/**
|
||||||
|
- _GET_
|
||||||
|
- [GetUser]()
|
||||||
|
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>`/whoami`</summary>
|
||||||
|
|
||||||
|
- [o-chi/cors.(*Cors).Handler-fm]()
|
||||||
|
- **/whoami**
|
||||||
|
- [SessionAuthMiddleware]()
|
||||||
|
- [LoginCtx]()
|
||||||
|
- **/**
|
||||||
|
- _GET_
|
||||||
|
- [Whoami]()
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
Total # of routes: 12
|
||||||
|
|
||||||
+5
-7
@@ -36,6 +36,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import Alpine from 'alpinejs'
|
import Alpine from 'alpinejs'
|
||||||
|
import { requireAuth } from '/src/auth.js'
|
||||||
import { logout, getchannels, getmessages } from '/src/api.js'
|
import { logout, getchannels, getmessages } from '/src/api.js'
|
||||||
|
|
||||||
window.app = () => ({
|
window.app = () => ({
|
||||||
@@ -45,12 +46,9 @@
|
|||||||
selectedChannel: null,
|
selectedChannel: null,
|
||||||
messages: [],
|
messages: [],
|
||||||
async init() {
|
async init() {
|
||||||
const res = await fetch('/api/whoami')
|
const username = await requireAuth()
|
||||||
if (res.status === 401) {
|
if (!username) return
|
||||||
window.location.href = '/login.html'
|
this.username = username
|
||||||
return
|
|
||||||
}
|
|
||||||
this.username = await res.text()
|
|
||||||
try {
|
try {
|
||||||
this.channels = await getchannels()
|
this.channels = await getchannels()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -62,7 +60,7 @@
|
|||||||
this.messages = []
|
this.messages = []
|
||||||
this.error = ''
|
this.error = ''
|
||||||
try {
|
try {
|
||||||
const from = new Date(Date.now() - 24 * 60 * 60 * 1000)
|
const from = new Date(Date.now() - 96 * 60 * 60 * 1000)
|
||||||
const to = new Date(Date.now())
|
const to = new Date(Date.now())
|
||||||
this.messages = await getmessages(ch.ID, { from, to })
|
this.messages = await getmessages(ch.ID, { from, to })
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
+62
-6
@@ -1,28 +1,84 @@
|
|||||||
|
const BASE = __API_URL__
|
||||||
|
const opts = { credentials: 'include' }
|
||||||
|
|
||||||
export async function login(username, password) {
|
export async function login(username, password) {
|
||||||
const form = new FormData()
|
const form = new FormData()
|
||||||
form.append('username', username)
|
form.append('username', username)
|
||||||
form.append('password', password)
|
form.append('password', password)
|
||||||
const res = await fetch('/api/login', { method: 'POST', body: form })
|
const res = await fetch(`${BASE}/login`, { ...opts, method: 'POST', body: form })
|
||||||
if (!res.ok) throw new Error(await res.text())
|
if (!res.ok) throw new Error(await res.text())
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function logout() {
|
export async function logout() {
|
||||||
const res = await fetch('/api/logout', { method: 'POST' })
|
const res = await fetch(`${BASE}/logout`, { ...opts, method: 'POST' })
|
||||||
if (!res.ok) throw new Error(await res.text())
|
if (!res.ok) throw new Error(await res.text())
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getchannels() {
|
export async function register(name, password) {
|
||||||
const res = await fetch('/api/channels')
|
const form = new FormData()
|
||||||
|
form.append('name', name)
|
||||||
|
form.append('password', password)
|
||||||
|
const res = await fetch(`${BASE}/register`, { ...opts, method: 'POST', body: form })
|
||||||
if (!res.ok) throw new Error(await res.text())
|
if (!res.ok) throw new Error(await res.text())
|
||||||
return res.json()
|
return res.json()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getchannels() {
|
||||||
|
const res = await fetch(`${BASE}/channels`, opts)
|
||||||
|
if (!res.ok) throw new Error(await res.text())
|
||||||
|
return res.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getchannel(channelid) {
|
||||||
|
const res = await fetch(`${BASE}/channels/${channelid}`, opts)
|
||||||
|
if (!res.ok) throw new Error(await res.text())
|
||||||
|
return res.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createchannel({ name, type = '', location = '', notes = '' }) {
|
||||||
|
const form = new FormData()
|
||||||
|
form.append('name', name)
|
||||||
|
form.append('type', type)
|
||||||
|
form.append('location', location)
|
||||||
|
form.append('notes', notes)
|
||||||
|
const res = await fetch(`${BASE}/channels`, { ...opts, method: 'POST', body: form })
|
||||||
|
if (!res.ok) throw new Error(await res.text())
|
||||||
|
return res.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deletechannel(channelid) {
|
||||||
|
const res = await fetch(`${BASE}/channels/${channelid}`, { ...opts, method: 'DELETE' })
|
||||||
|
if (!res.ok) throw new Error(await res.text())
|
||||||
|
}
|
||||||
|
|
||||||
export async function getmessages(channelid, { from, to } = {}) {
|
export async function getmessages(channelid, { from, to } = {}) {
|
||||||
const params = new URLSearchParams()
|
const params = new URLSearchParams()
|
||||||
if (from) params.set('from', from.toISOString())
|
if (from) params.set('from', from.toISOString())
|
||||||
if (to) params.set('to', to.toISOString())
|
if (to) params.set('to', to.toISOString())
|
||||||
const query = params.size ? `?${params}` : ''
|
const query = params.size ? `?${params}` : ''
|
||||||
const res = await fetch(`/api/channels/${channelid}/messages${query}`)
|
const res = await fetch(`${BASE}/channels/${channelid}/messages${query}`, opts)
|
||||||
if (!res.ok) throw new Error(await res.text())
|
if (!res.ok) throw new Error(await res.text())
|
||||||
return res.json()
|
return res.json()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getmessage(channelid, messageid) {
|
||||||
|
const res = await fetch(`${BASE}/channels/${channelid}/messages/${messageid}`, opts)
|
||||||
|
if (!res.ok) throw new Error(await res.text())
|
||||||
|
return res.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getfileurl(fileid) {
|
||||||
|
return `${BASE}/files/${fileid}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getusers() {
|
||||||
|
const res = await fetch(`${BASE}/users`, opts)
|
||||||
|
if (!res.ok) throw new Error(await res.text())
|
||||||
|
return res.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getuser(userid) {
|
||||||
|
const res = await fetch(`${BASE}/users/${userid}`, opts)
|
||||||
|
if (!res.ok) throw new Error(await res.text())
|
||||||
|
return res.json()
|
||||||
|
}
|
||||||
|
|||||||
+6
-2
@@ -1,12 +1,16 @@
|
|||||||
|
const BASE = __API_URL__
|
||||||
|
|
||||||
export async function requireAuth() {
|
export async function requireAuth() {
|
||||||
const res = await fetch('/api/whoami')
|
const res = await fetch(`${BASE}/whoami`, { credentials: 'include' })
|
||||||
if (res.status === 401) {
|
if (res.status === 401) {
|
||||||
window.location.href = '/login.html'
|
window.location.href = '/login.html'
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
return res.text()
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function redirectIfAuthed() {
|
export async function redirectIfAuthed() {
|
||||||
const res = await fetch('/api/whoami')
|
const res = await fetch(`${BASE}/whoami`, { credentials: 'include' })
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
window.location.href = '/'
|
window.location.href = '/'
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-7
@@ -1,17 +1,14 @@
|
|||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import { resolve } from 'path'
|
import { resolve } from 'path'
|
||||||
|
|
||||||
const API_URL = process.env.API_URL ?? 'http://192.168.56.1:3000'
|
const API_URL = process.env.API_URL ?? 'http://localhost:3000'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
define: {
|
||||||
|
__API_URL__: JSON.stringify(API_URL),
|
||||||
|
},
|
||||||
server: {
|
server: {
|
||||||
port: 5173,
|
port: 5173,
|
||||||
proxy: {
|
|
||||||
'/api': {
|
|
||||||
target: API_URL,
|
|
||||||
rewrite: (path) => path.replace(/^\/api/, ''),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
outDir: 'dist',
|
outDir: 'dist',
|
||||||
|
|||||||
Reference in New Issue
Block a user