Compare commits
No commits in common. "b3cd25117f96abe5172338e83655e3e7b10aa501" and "171ca5e52c698c824d2cdd335b3bfe5d7c327620" have entirely different histories.
b3cd25117f
...
171ca5e52c
@ -1,202 +0,0 @@
|
|||||||
package db
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/H1K0/Kiraku/internal/models"
|
|
||||||
"github.com/jackc/pgx/v5"
|
|
||||||
"github.com/jackc/pgx/v5/pgconn"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CreditsGetByPerson(ctx context.Context, user_id, person_id, sort string) (credits []models.PersonCredit, statusCode int, err error) {
|
|
||||||
ok, _ := UserAuth(ctx, user_id)
|
|
||||||
if !ok {
|
|
||||||
err = fmt.Errorf("unauthorized")
|
|
||||||
statusCode = http.StatusUnauthorized
|
|
||||||
return
|
|
||||||
}
|
|
||||||
query := "SELECT t.id AS track_id, t.name AS track_name, t.duration AS track_duration, COALESCE(t.release_date::text, '') AS track_releaseDate, t.acquire_datetime AS track_acquireDatetime, r.id AS role_id, r.name AS role_name, COALESCE(c.alias, '') AS alias " +
|
|
||||||
"FROM credits c " +
|
|
||||||
"JOIN tracks t ON t.id=c.track_id " +
|
|
||||||
"JOIN roles r ON r.id=c.role_id " +
|
|
||||||
"WHERE c.person_id=$1"
|
|
||||||
if sort != "" {
|
|
||||||
sort_options := strings.Split(sort, ",")
|
|
||||||
query += " ORDER BY "
|
|
||||||
for i, sort_option := range sort_options {
|
|
||||||
sort_order := sort_option[:1]
|
|
||||||
sort_field := sort_option[1:]
|
|
||||||
switch sort_order {
|
|
||||||
case "+":
|
|
||||||
sort_order = "ASC"
|
|
||||||
case "-":
|
|
||||||
sort_order = "DESC"
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("invalid sorting order mark: %q", sort)
|
|
||||||
statusCode = http.StatusBadRequest
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch sort_field {
|
|
||||||
case "track.name":
|
|
||||||
fallthrough
|
|
||||||
case "track.releaseDate":
|
|
||||||
fallthrough
|
|
||||||
case "track.acquireDatetime":
|
|
||||||
fallthrough
|
|
||||||
case "track.duration":
|
|
||||||
fallthrough
|
|
||||||
case "role.name":
|
|
||||||
sort_field = strings.ReplaceAll(sort_field, ".", "_")
|
|
||||||
case "track.sortName":
|
|
||||||
sort_field = "COALESCE(t.sort_name, t.name)"
|
|
||||||
case "alias":
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("invalid sorting field: %q", sort_field)
|
|
||||||
statusCode = http.StatusBadRequest
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if i > 0 {
|
|
||||||
query += ", "
|
|
||||||
}
|
|
||||||
query += fmt.Sprintf("%s %s NULLS LAST", sort_field, sort_order)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
row := connPool.QueryRow(ctx, "SELECT 1 FROM persons WHERE id=$1", person_id)
|
|
||||||
err = row.Scan(nil)
|
|
||||||
if err != nil {
|
|
||||||
if err == pgx.ErrNoRows {
|
|
||||||
err = fmt.Errorf("not found")
|
|
||||||
statusCode = http.StatusNotFound
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pgErr := err.(*pgconn.PgError)
|
|
||||||
if pgErr.Code == "22P02" {
|
|
||||||
err = fmt.Errorf("%s", pgErr.Message)
|
|
||||||
statusCode = http.StatusBadRequest
|
|
||||||
} else {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rows, err := connPool.Query(ctx, query, person_id)
|
|
||||||
if err != nil {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
return
|
|
||||||
}
|
|
||||||
count := 0
|
|
||||||
for rows.Next() {
|
|
||||||
var credit models.PersonCredit
|
|
||||||
err = rows.Scan(
|
|
||||||
&credit.Track.ID, &credit.Track.Name, &credit.Track.Duration, &credit.Track.ReleaseDate, &credit.Track.AcquireDatetime,
|
|
||||||
&credit.Role.ID, &credit.Role.Name, &credit.Alias,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
return
|
|
||||||
}
|
|
||||||
credits = append(credits, credit)
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
err = rows.Err()
|
|
||||||
if err != nil {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
return
|
|
||||||
}
|
|
||||||
statusCode = http.StatusOK
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreditsGetByTrack(ctx context.Context, user_id, track_id, sort string) (credits []models.TrackCredit, statusCode int, err error) {
|
|
||||||
ok, _ := UserAuth(ctx, user_id)
|
|
||||||
if !ok {
|
|
||||||
err = fmt.Errorf("unauthorized")
|
|
||||||
statusCode = http.StatusUnauthorized
|
|
||||||
return
|
|
||||||
}
|
|
||||||
query := "SELECT p.id AS person_id, p.name AS person_name, COALESCE(p.sort_name, '') AS person_sortName, r.id AS role_id, r.name AS role_name, COALESCE(c.alias, '') AS alias " +
|
|
||||||
"FROM credits c " +
|
|
||||||
"JOIN persons p ON p.id=c.person_id " +
|
|
||||||
"JOIN roles r ON r.id=c.role_id " +
|
|
||||||
"WHERE c.track_id=$1"
|
|
||||||
if sort != "" {
|
|
||||||
sort_options := strings.Split(sort, ",")
|
|
||||||
query += " ORDER BY "
|
|
||||||
for i, sort_option := range sort_options {
|
|
||||||
sort_order := sort_option[:1]
|
|
||||||
sort_field := sort_option[1:]
|
|
||||||
switch sort_order {
|
|
||||||
case "+":
|
|
||||||
sort_order = "ASC"
|
|
||||||
case "-":
|
|
||||||
sort_order = "DESC"
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("invalid sorting order mark: %q", sort)
|
|
||||||
statusCode = http.StatusBadRequest
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch sort_field {
|
|
||||||
case "person.name":
|
|
||||||
fallthrough
|
|
||||||
case "role.name":
|
|
||||||
sort_field = strings.ReplaceAll(sort_field, ".", "_")
|
|
||||||
case "person.sortName":
|
|
||||||
sort_field = "COALESCE(p.sort_name, p.name)"
|
|
||||||
case "alias":
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("invalid sorting field: %q", sort_field)
|
|
||||||
statusCode = http.StatusBadRequest
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if i > 0 {
|
|
||||||
query += ", "
|
|
||||||
}
|
|
||||||
query += fmt.Sprintf("%s %s NULLS LAST", sort_field, sort_order)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
row := connPool.QueryRow(ctx, "SELECT 1 FROM tracks WHERE id=$1", track_id)
|
|
||||||
err = row.Scan(nil)
|
|
||||||
if err != nil {
|
|
||||||
if err == pgx.ErrNoRows {
|
|
||||||
err = fmt.Errorf("not found")
|
|
||||||
statusCode = http.StatusNotFound
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pgErr := err.(*pgconn.PgError)
|
|
||||||
if pgErr.Code == "22P02" {
|
|
||||||
err = fmt.Errorf("%s", pgErr.Message)
|
|
||||||
statusCode = http.StatusBadRequest
|
|
||||||
} else {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rows, err := connPool.Query(ctx, query, track_id)
|
|
||||||
if err != nil {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
return
|
|
||||||
}
|
|
||||||
count := 0
|
|
||||||
for rows.Next() {
|
|
||||||
var credit models.TrackCredit
|
|
||||||
err = rows.Scan(
|
|
||||||
&credit.Person.ID, &credit.Person.Name, &credit.Person.SortName,
|
|
||||||
&credit.Role.ID, &credit.Role.Name, &credit.Alias,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
return
|
|
||||||
}
|
|
||||||
credits = append(credits, credit)
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
err = rows.Err()
|
|
||||||
if err != nil {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
return
|
|
||||||
}
|
|
||||||
statusCode = http.StatusOK
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@ -4,9 +4,12 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/H1K0/Kiraku/internal/models"
|
||||||
"github.com/jackc/pgx/v5"
|
"github.com/jackc/pgx/v5"
|
||||||
|
"github.com/jackc/pgx/v5/pgconn"
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -47,3 +50,270 @@ func transaction(ctx context.Context, handler func(pgx.Tx) (statusCode int, err
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#region Users
|
||||||
|
|
||||||
|
func UserLogin(ctx context.Context, login, password string) (user_id string, err error) {
|
||||||
|
row := connPool.QueryRow(ctx, "SELECT id FROM users WHERE login=$1 AND password=crypt($2, password)", login, password)
|
||||||
|
err = row.Scan(&user_id)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func UserAuth(ctx context.Context, user_id string) (ok, editor bool) {
|
||||||
|
row := connPool.QueryRow(ctx, "SELECT editor FROM users WHERE id=$1", user_id)
|
||||||
|
err := row.Scan(&editor)
|
||||||
|
ok = (err == nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion Users
|
||||||
|
|
||||||
|
//#region Persons
|
||||||
|
|
||||||
|
func PersonsGet(ctx context.Context, user_id, filter, sort string, limit, offset int) (persons models.Persons, statusCode int, err error) {
|
||||||
|
ok, _ := UserAuth(ctx, user_id)
|
||||||
|
if !ok {
|
||||||
|
err = fmt.Errorf("unauthorized")
|
||||||
|
statusCode = http.StatusUnauthorized
|
||||||
|
return
|
||||||
|
}
|
||||||
|
queryGet := "SELECT id, name, COALESCE(sort_name, '') FROM persons WHERE POSITION($1 IN LOWER(name))>0 OR POSITION($1 IN LOWER(sort_name))>0"
|
||||||
|
if sort != "" {
|
||||||
|
sort_options := strings.Split(sort, ",")
|
||||||
|
queryGet += " ORDER BY "
|
||||||
|
for i, sort_option := range sort_options {
|
||||||
|
sort_order := sort_option[:1]
|
||||||
|
sort_field := sort_option[1:]
|
||||||
|
switch sort_order {
|
||||||
|
case "+":
|
||||||
|
sort_order = "ASC"
|
||||||
|
case "-":
|
||||||
|
sort_order = "DESC"
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("invalid sorting order mark: %q", sort)
|
||||||
|
statusCode = http.StatusBadRequest
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch sort_field {
|
||||||
|
case "name":
|
||||||
|
case "sortName":
|
||||||
|
sort_field = "COALESCE(sort_name, name)"
|
||||||
|
case "birthdate":
|
||||||
|
case "deathdate":
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("invalid sorting field: %q", sort_field)
|
||||||
|
statusCode = http.StatusBadRequest
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if i > 0 {
|
||||||
|
queryGet += ", "
|
||||||
|
}
|
||||||
|
queryGet += fmt.Sprintf("%s %s NULLS LAST", sort_field, sort_order)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
queryCount := queryGet
|
||||||
|
if limit >= 0 {
|
||||||
|
queryGet += fmt.Sprintf(" LIMIT %d", limit)
|
||||||
|
}
|
||||||
|
if offset > 0 {
|
||||||
|
queryGet += fmt.Sprintf(" OFFSET %d", offset)
|
||||||
|
}
|
||||||
|
filter = strings.ToLower(filter)
|
||||||
|
statusCode, err = transaction(ctx, func(tx pgx.Tx) (statusCode int, err error) {
|
||||||
|
rows, err := tx.Query(ctx, queryGet, filter)
|
||||||
|
if err != nil {
|
||||||
|
statusCode = http.StatusInternalServerError
|
||||||
|
return
|
||||||
|
}
|
||||||
|
count := 0
|
||||||
|
for rows.Next() {
|
||||||
|
var person models.PersonBrief
|
||||||
|
err = rows.Scan(&person.ID, &person.Name, &person.SortName)
|
||||||
|
if err != nil {
|
||||||
|
statusCode = http.StatusInternalServerError
|
||||||
|
return
|
||||||
|
}
|
||||||
|
persons.Persons = append(persons.Persons, person)
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
err = rows.Err()
|
||||||
|
if err != nil {
|
||||||
|
statusCode = http.StatusInternalServerError
|
||||||
|
return
|
||||||
|
}
|
||||||
|
persons.Pagination.Limit = limit
|
||||||
|
persons.Pagination.Offset = offset
|
||||||
|
persons.Pagination.Count = count
|
||||||
|
queryCount = fmt.Sprintf("SELECT COUNT(*) FROM (%s) tmp", queryCount)
|
||||||
|
row := tx.QueryRow(ctx, queryCount, filter)
|
||||||
|
err = row.Scan(&persons.Pagination.Total)
|
||||||
|
if err != nil {
|
||||||
|
statusCode = http.StatusInternalServerError
|
||||||
|
}
|
||||||
|
return
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
statusCode = http.StatusOK
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func PersonGet(ctx context.Context, user_id, person_id string) (person models.Person, statusCode int, err error) {
|
||||||
|
ok, _ := UserAuth(ctx, user_id)
|
||||||
|
if !ok {
|
||||||
|
err = fmt.Errorf("unauthorized")
|
||||||
|
statusCode = http.StatusUnauthorized
|
||||||
|
return
|
||||||
|
}
|
||||||
|
row := connPool.QueryRow(ctx, "SELECT id, name, COALESCE(sort_name, ''), COALESCE(TO_CHAR(birthdate, 'YYYY-MM-DD'), ''), COALESCE(TO_CHAR(deathdate, 'YYYY-MM-DD'), ''), COALESCE(info, '') FROM persons WHERE id=$1", person_id)
|
||||||
|
err = row.Scan(&person.ID, &person.Name, &person.SortName, &person.Birthdate, &person.Deathdate, &person.Deathdate)
|
||||||
|
if err != nil {
|
||||||
|
pgErr := err.(*pgconn.PgError)
|
||||||
|
if err == pgx.ErrNoRows {
|
||||||
|
err = fmt.Errorf("not found")
|
||||||
|
statusCode = http.StatusNotFound
|
||||||
|
} else if pgErr.Code == "22P02" || pgErr.Code == "22007" {
|
||||||
|
err = fmt.Errorf("%s", pgErr.Message)
|
||||||
|
statusCode = http.StatusBadRequest
|
||||||
|
} else {
|
||||||
|
statusCode = http.StatusInternalServerError
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
statusCode = http.StatusOK
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func PersonAdd(ctx context.Context, user_id, name, sortName, birthdate, deathdate, info string) (person models.Person, statusCode int, err error) {
|
||||||
|
ok, editor := UserAuth(ctx, user_id)
|
||||||
|
if !ok {
|
||||||
|
err = fmt.Errorf("unauthorized")
|
||||||
|
statusCode = http.StatusUnauthorized
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !editor {
|
||||||
|
err = fmt.Errorf("not allowed")
|
||||||
|
statusCode = http.StatusForbidden
|
||||||
|
return
|
||||||
|
}
|
||||||
|
row := connPool.QueryRow(
|
||||||
|
ctx,
|
||||||
|
"INSERT INTO persons (name, sort_name, birthdate, deathdate, info) "+
|
||||||
|
"VALUES ($1, NULLIF($2, ''), NULLIF($3, '')::date, NULLIF($4, '')::date, NULLIF($5, '')) "+
|
||||||
|
"RETURNING id, name, COALESCE(sort_name, ''), COALESCE(TO_CHAR(birthdate, 'YYYY-MM-DD'), ''), COALESCE(TO_CHAR(deathdate, 'YYYY-MM-DD'), ''), COALESCE(info, '')",
|
||||||
|
name, sortName, birthdate, deathdate, info,
|
||||||
|
)
|
||||||
|
err = row.Scan(&person.ID, &person.Name, &person.SortName, &person.Birthdate, &person.Deathdate, &person.Info)
|
||||||
|
if err != nil {
|
||||||
|
pgErr := err.(*pgconn.PgError)
|
||||||
|
if pgErr.Code == "22P02" || pgErr.Code == "22007" {
|
||||||
|
err = fmt.Errorf("%s", pgErr.Message)
|
||||||
|
statusCode = http.StatusBadRequest
|
||||||
|
} else if pgErr.Code == "23505" {
|
||||||
|
err = fmt.Errorf("a person with this name already exists")
|
||||||
|
statusCode = http.StatusConflict
|
||||||
|
} else {
|
||||||
|
statusCode = http.StatusInternalServerError
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
statusCode = http.StatusOK
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func PersonUpdate(ctx context.Context, user_id, person_id string, values map[string]string) (person models.Person, statusCode int, err error) {
|
||||||
|
ok, editor := UserAuth(ctx, user_id)
|
||||||
|
if !ok {
|
||||||
|
err = fmt.Errorf("unauthorized")
|
||||||
|
statusCode = http.StatusUnauthorized
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !editor {
|
||||||
|
err = fmt.Errorf("not allowed")
|
||||||
|
statusCode = http.StatusForbidden
|
||||||
|
return
|
||||||
|
}
|
||||||
|
statusCode, err = transaction(ctx, func(tx pgx.Tx) (statusCode int, err error) {
|
||||||
|
for _, field := range []string{"name", "sortName", "birthdate", "deathdate", "info"} {
|
||||||
|
value, ok := values[field]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if field == "sortName" {
|
||||||
|
field = "sort_name"
|
||||||
|
}
|
||||||
|
var query string
|
||||||
|
if field == "birthdate" || field == "deathdate" {
|
||||||
|
query = fmt.Sprintf("UPDATE persons SET %s=NULLIF($2, '')::date WHERE id=$1", field)
|
||||||
|
} else {
|
||||||
|
query = fmt.Sprintf("UPDATE persons SET %s=NULLIF($2, '') WHERE id=$1", field)
|
||||||
|
}
|
||||||
|
var commandTag pgconn.CommandTag
|
||||||
|
commandTag, err = tx.Exec(ctx, query, person_id, value)
|
||||||
|
if err != nil {
|
||||||
|
pgErr := err.(*pgconn.PgError)
|
||||||
|
if pgErr.Code == "22P02" || pgErr.Code == "22007" {
|
||||||
|
err = fmt.Errorf("%s", pgErr.Message)
|
||||||
|
statusCode = http.StatusBadRequest
|
||||||
|
} else if pgErr.Code == "23505" {
|
||||||
|
err = fmt.Errorf("a person with this name already exists")
|
||||||
|
statusCode = http.StatusConflict
|
||||||
|
} else {
|
||||||
|
statusCode = http.StatusInternalServerError
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if commandTag.RowsAffected() == 0 {
|
||||||
|
err = fmt.Errorf("not found")
|
||||||
|
statusCode = http.StatusNotFound
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
row := tx.QueryRow(ctx, "SELECT id, name, COALESCE(sort_name, ''), COALESCE(TO_CHAR(birthdate, 'YYYY-MM-DD'), ''), COALESCE(TO_CHAR(deathdate, 'YYYY-MM-DD'), ''), COALESCE(info, '') FROM persons WHERE id=$1", person_id)
|
||||||
|
err = row.Scan(&person.ID, &person.Name, &person.SortName, &person.Birthdate, &person.Deathdate, &person.Info)
|
||||||
|
if err != nil {
|
||||||
|
statusCode = http.StatusInternalServerError
|
||||||
|
}
|
||||||
|
return
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
statusCode = http.StatusOK
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func PersonDelete(ctx context.Context, user_id, person_id string) (statusCode int, err error) {
|
||||||
|
ok, editor := UserAuth(ctx, user_id)
|
||||||
|
if !ok {
|
||||||
|
err = fmt.Errorf("unauthorized")
|
||||||
|
statusCode = http.StatusUnauthorized
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !editor {
|
||||||
|
err = fmt.Errorf("not allowed")
|
||||||
|
statusCode = http.StatusForbidden
|
||||||
|
return
|
||||||
|
}
|
||||||
|
commandTag, err := connPool.Exec(ctx, "DELETE FROM persons WHERE id=$1", person_id)
|
||||||
|
if err != nil {
|
||||||
|
pgErr := err.(*pgconn.PgError)
|
||||||
|
if pgErr.Code == "22P02" {
|
||||||
|
err = fmt.Errorf("%s", pgErr.Message)
|
||||||
|
statusCode = http.StatusBadRequest
|
||||||
|
} else {
|
||||||
|
statusCode = http.StatusInternalServerError
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if commandTag.RowsAffected() == 0 {
|
||||||
|
err = fmt.Errorf("not found")
|
||||||
|
statusCode = http.StatusNotFound
|
||||||
|
return
|
||||||
|
}
|
||||||
|
statusCode = http.StatusNoContent
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion Persons
|
||||||
|
|||||||
@ -1,260 +0,0 @@
|
|||||||
package db
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/H1K0/Kiraku/internal/models"
|
|
||||||
"github.com/jackc/pgx/v5"
|
|
||||||
"github.com/jackc/pgx/v5/pgconn"
|
|
||||||
)
|
|
||||||
|
|
||||||
func PersonGetSlice(ctx context.Context, user_id, filter, sort string, limit, offset int) (persons models.PersonSlice, statusCode int, err error) {
|
|
||||||
ok, _ := UserAuth(ctx, user_id)
|
|
||||||
if !ok {
|
|
||||||
err = fmt.Errorf("unauthorized")
|
|
||||||
statusCode = http.StatusUnauthorized
|
|
||||||
return
|
|
||||||
}
|
|
||||||
queryGet := "SELECT id, name, COALESCE(sort_name, '') FROM persons WHERE POSITION($1 IN LOWER(name))>0 OR POSITION($1 IN LOWER(sort_name))>0"
|
|
||||||
if sort != "" {
|
|
||||||
sort_options := strings.Split(sort, ",")
|
|
||||||
queryGet += " ORDER BY "
|
|
||||||
for i, sort_option := range sort_options {
|
|
||||||
sort_order := sort_option[:1]
|
|
||||||
sort_field := sort_option[1:]
|
|
||||||
switch sort_order {
|
|
||||||
case "+":
|
|
||||||
sort_order = "ASC"
|
|
||||||
case "-":
|
|
||||||
sort_order = "DESC"
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("invalid sorting order mark: %q", sort)
|
|
||||||
statusCode = http.StatusBadRequest
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch sort_field {
|
|
||||||
case "name":
|
|
||||||
case "sortName":
|
|
||||||
sort_field = "COALESCE(sort_name, name)"
|
|
||||||
case "birthdate":
|
|
||||||
case "deathdate":
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("invalid sorting field: %q", sort_field)
|
|
||||||
statusCode = http.StatusBadRequest
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if i > 0 {
|
|
||||||
queryGet += ", "
|
|
||||||
}
|
|
||||||
queryGet += fmt.Sprintf("%s %s NULLS LAST", sort_field, sort_order)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
queryCount := queryGet
|
|
||||||
if limit >= 0 {
|
|
||||||
queryGet += fmt.Sprintf(" LIMIT %d", limit)
|
|
||||||
}
|
|
||||||
if offset > 0 {
|
|
||||||
queryGet += fmt.Sprintf(" OFFSET %d", offset)
|
|
||||||
}
|
|
||||||
filter = strings.ToLower(filter)
|
|
||||||
statusCode, err = transaction(ctx, func(tx pgx.Tx) (statusCode int, err error) {
|
|
||||||
rows, err := tx.Query(ctx, queryGet, filter)
|
|
||||||
if err != nil {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
return
|
|
||||||
}
|
|
||||||
count := 0
|
|
||||||
for rows.Next() {
|
|
||||||
var person models.PersonBrief
|
|
||||||
err = rows.Scan(&person.ID, &person.Name, &person.SortName)
|
|
||||||
if err != nil {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
return
|
|
||||||
}
|
|
||||||
persons.Persons = append(persons.Persons, person)
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
err = rows.Err()
|
|
||||||
if err != nil {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
return
|
|
||||||
}
|
|
||||||
persons.Pagination.Limit = limit
|
|
||||||
persons.Pagination.Offset = offset
|
|
||||||
persons.Pagination.Count = count
|
|
||||||
queryCount = fmt.Sprintf("SELECT COUNT(*) FROM (%s) tmp", queryCount)
|
|
||||||
row := tx.QueryRow(ctx, queryCount, filter)
|
|
||||||
err = row.Scan(&persons.Pagination.Total)
|
|
||||||
if err != nil {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
return
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
statusCode = http.StatusOK
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func PersonGet(ctx context.Context, user_id, person_id string) (person models.Person, statusCode int, err error) {
|
|
||||||
ok, _ := UserAuth(ctx, user_id)
|
|
||||||
if !ok {
|
|
||||||
err = fmt.Errorf("unauthorized")
|
|
||||||
statusCode = http.StatusUnauthorized
|
|
||||||
return
|
|
||||||
}
|
|
||||||
row := connPool.QueryRow(ctx, "SELECT id, name, COALESCE(sort_name, ''), COALESCE(TO_CHAR(birthdate, 'YYYY-MM-DD'), ''), COALESCE(TO_CHAR(deathdate, 'YYYY-MM-DD'), ''), COALESCE(info, '') FROM persons WHERE id=$1", person_id)
|
|
||||||
err = row.Scan(&person.ID, &person.Name, &person.SortName, &person.Birthdate, &person.Deathdate, &person.Deathdate)
|
|
||||||
if err != nil {
|
|
||||||
if err == pgx.ErrNoRows {
|
|
||||||
err = fmt.Errorf("not found")
|
|
||||||
statusCode = http.StatusNotFound
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pgErr := err.(*pgconn.PgError)
|
|
||||||
if pgErr.Code == "22P02" || pgErr.Code == "22007" {
|
|
||||||
err = fmt.Errorf("%s", pgErr.Message)
|
|
||||||
statusCode = http.StatusBadRequest
|
|
||||||
} else {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
statusCode = http.StatusOK
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func PersonAdd(ctx context.Context, user_id, name, sortName, birthdate, deathdate, info string) (person models.Person, statusCode int, err error) {
|
|
||||||
ok, editor := UserAuth(ctx, user_id)
|
|
||||||
if !ok {
|
|
||||||
err = fmt.Errorf("unauthorized")
|
|
||||||
statusCode = http.StatusUnauthorized
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !editor {
|
|
||||||
err = fmt.Errorf("not allowed")
|
|
||||||
statusCode = http.StatusForbidden
|
|
||||||
return
|
|
||||||
}
|
|
||||||
row := connPool.QueryRow(
|
|
||||||
ctx,
|
|
||||||
"INSERT INTO persons (name, sort_name, birthdate, deathdate, info) "+
|
|
||||||
"VALUES ($1, NULLIF($2, ''), NULLIF($3, '')::date, NULLIF($4, '')::date, NULLIF($5, '')) "+
|
|
||||||
"RETURNING id, name, COALESCE(sort_name, ''), COALESCE(TO_CHAR(birthdate, 'YYYY-MM-DD'), ''), COALESCE(TO_CHAR(deathdate, 'YYYY-MM-DD'), ''), COALESCE(info, '')",
|
|
||||||
name, sortName, birthdate, deathdate, info,
|
|
||||||
)
|
|
||||||
err = row.Scan(&person.ID, &person.Name, &person.SortName, &person.Birthdate, &person.Deathdate, &person.Info)
|
|
||||||
if err != nil {
|
|
||||||
pgErr := err.(*pgconn.PgError)
|
|
||||||
if pgErr.Code == "22P02" || pgErr.Code == "22007" {
|
|
||||||
err = fmt.Errorf("%s", pgErr.Message)
|
|
||||||
statusCode = http.StatusBadRequest
|
|
||||||
} else if pgErr.Code == "23505" {
|
|
||||||
err = fmt.Errorf("a person with this name already exists")
|
|
||||||
statusCode = http.StatusConflict
|
|
||||||
} else {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
statusCode = http.StatusOK
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func PersonUpdate(ctx context.Context, user_id, person_id string, values map[string]string) (person models.Person, statusCode int, err error) {
|
|
||||||
ok, editor := UserAuth(ctx, user_id)
|
|
||||||
if !ok {
|
|
||||||
err = fmt.Errorf("unauthorized")
|
|
||||||
statusCode = http.StatusUnauthorized
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !editor {
|
|
||||||
err = fmt.Errorf("not allowed")
|
|
||||||
statusCode = http.StatusForbidden
|
|
||||||
return
|
|
||||||
}
|
|
||||||
statusCode, err = transaction(ctx, func(tx pgx.Tx) (statusCode int, err error) {
|
|
||||||
for _, field := range []string{"name", "sortName", "birthdate", "deathdate", "info"} {
|
|
||||||
value, ok := values[field]
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if field == "sortName" {
|
|
||||||
field = "sort_name"
|
|
||||||
}
|
|
||||||
var query string
|
|
||||||
if field == "birthdate" || field == "deathdate" {
|
|
||||||
query = fmt.Sprintf("UPDATE persons SET %s=NULLIF($2, '')::date WHERE id=$1", field)
|
|
||||||
} else {
|
|
||||||
query = fmt.Sprintf("UPDATE persons SET %s=NULLIF($2, '') WHERE id=$1", field)
|
|
||||||
}
|
|
||||||
var commandTag pgconn.CommandTag
|
|
||||||
commandTag, err = tx.Exec(ctx, query, person_id, value)
|
|
||||||
if err != nil {
|
|
||||||
pgErr := err.(*pgconn.PgError)
|
|
||||||
if pgErr.Code == "22P02" || pgErr.Code == "22007" {
|
|
||||||
err = fmt.Errorf("%s", pgErr.Message)
|
|
||||||
statusCode = http.StatusBadRequest
|
|
||||||
} else if pgErr.Code == "23505" {
|
|
||||||
err = fmt.Errorf("a person with this name already exists")
|
|
||||||
statusCode = http.StatusConflict
|
|
||||||
} else {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if commandTag.RowsAffected() == 0 {
|
|
||||||
err = fmt.Errorf("not found")
|
|
||||||
statusCode = http.StatusNotFound
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
row := tx.QueryRow(ctx, "SELECT id, name, COALESCE(sort_name, ''), COALESCE(TO_CHAR(birthdate, 'YYYY-MM-DD'), ''), COALESCE(TO_CHAR(deathdate, 'YYYY-MM-DD'), ''), COALESCE(info, '') FROM persons WHERE id=$1", person_id)
|
|
||||||
err = row.Scan(&person.ID, &person.Name, &person.SortName, &person.Birthdate, &person.Deathdate, &person.Info)
|
|
||||||
if err != nil {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
return
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
statusCode = http.StatusOK
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func PersonDelete(ctx context.Context, user_id, person_id string) (statusCode int, err error) {
|
|
||||||
ok, editor := UserAuth(ctx, user_id)
|
|
||||||
if !ok {
|
|
||||||
err = fmt.Errorf("unauthorized")
|
|
||||||
statusCode = http.StatusUnauthorized
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !editor {
|
|
||||||
err = fmt.Errorf("not allowed")
|
|
||||||
statusCode = http.StatusForbidden
|
|
||||||
return
|
|
||||||
}
|
|
||||||
commandTag, err := connPool.Exec(ctx, "DELETE FROM persons WHERE id=$1", person_id)
|
|
||||||
if err != nil {
|
|
||||||
pgErr := err.(*pgconn.PgError)
|
|
||||||
if pgErr.Code == "22P02" {
|
|
||||||
err = fmt.Errorf("%s", pgErr.Message)
|
|
||||||
statusCode = http.StatusBadRequest
|
|
||||||
} else {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if commandTag.RowsAffected() == 0 {
|
|
||||||
err = fmt.Errorf("not found")
|
|
||||||
statusCode = http.StatusNotFound
|
|
||||||
return
|
|
||||||
}
|
|
||||||
statusCode = http.StatusNoContent
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@ -1,241 +0,0 @@
|
|||||||
package db
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/H1K0/Kiraku/internal/models"
|
|
||||||
"github.com/jackc/pgx/v5"
|
|
||||||
"github.com/jackc/pgx/v5/pgconn"
|
|
||||||
)
|
|
||||||
|
|
||||||
func RoleGetSlice(ctx context.Context, user_id, filter, sort string, limit, offset int) (roles models.RoleSlice, statusCode int, err error) {
|
|
||||||
ok, _ := UserAuth(ctx, user_id)
|
|
||||||
if !ok {
|
|
||||||
err = fmt.Errorf("unauthorized")
|
|
||||||
statusCode = http.StatusUnauthorized
|
|
||||||
return
|
|
||||||
}
|
|
||||||
queryGet := "SELECT id, name FROM roles WHERE POSITION($1 IN LOWER(name))>0"
|
|
||||||
if sort != "" {
|
|
||||||
sort_options := strings.Split(sort, ",")
|
|
||||||
queryGet += " ORDER BY "
|
|
||||||
for i, sort_option := range sort_options {
|
|
||||||
sort_order := sort_option[:1]
|
|
||||||
sort_field := sort_option[1:]
|
|
||||||
switch sort_order {
|
|
||||||
case "+":
|
|
||||||
sort_order = "ASC"
|
|
||||||
case "-":
|
|
||||||
sort_order = "DESC"
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("invalid sorting order mark: %q", sort)
|
|
||||||
statusCode = http.StatusBadRequest
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch sort_field {
|
|
||||||
case "name":
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("invalid sorting field: %q", sort_field)
|
|
||||||
statusCode = http.StatusBadRequest
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if i > 0 {
|
|
||||||
queryGet += ", "
|
|
||||||
}
|
|
||||||
queryGet += fmt.Sprintf("%s %s NULLS LAST", sort_field, sort_order)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
queryCount := queryGet
|
|
||||||
if limit >= 0 {
|
|
||||||
queryGet += fmt.Sprintf(" LIMIT %d", limit)
|
|
||||||
}
|
|
||||||
if offset > 0 {
|
|
||||||
queryGet += fmt.Sprintf(" OFFSET %d", offset)
|
|
||||||
}
|
|
||||||
filter = strings.ToLower(filter)
|
|
||||||
statusCode, err = transaction(ctx, func(tx pgx.Tx) (statusCode int, err error) {
|
|
||||||
rows, err := tx.Query(ctx, queryGet, filter)
|
|
||||||
if err != nil {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
return
|
|
||||||
}
|
|
||||||
count := 0
|
|
||||||
for rows.Next() {
|
|
||||||
var role models.Role
|
|
||||||
err = rows.Scan(&role.ID, &role.Name)
|
|
||||||
if err != nil {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
return
|
|
||||||
}
|
|
||||||
roles.Roles = append(roles.Roles, role)
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
err = rows.Err()
|
|
||||||
if err != nil {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
return
|
|
||||||
}
|
|
||||||
roles.Pagination.Limit = limit
|
|
||||||
roles.Pagination.Offset = offset
|
|
||||||
roles.Pagination.Count = count
|
|
||||||
queryCount = fmt.Sprintf("SELECT COUNT(*) FROM (%s) tmp", queryCount)
|
|
||||||
row := tx.QueryRow(ctx, queryCount, filter)
|
|
||||||
err = row.Scan(&roles.Pagination.Total)
|
|
||||||
if err != nil {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
return
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
statusCode = http.StatusOK
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func RoleGet(ctx context.Context, user_id, person_id string) (role models.Role, statusCode int, err error) {
|
|
||||||
ok, _ := UserAuth(ctx, user_id)
|
|
||||||
if !ok {
|
|
||||||
err = fmt.Errorf("unauthorized")
|
|
||||||
statusCode = http.StatusUnauthorized
|
|
||||||
return
|
|
||||||
}
|
|
||||||
row := connPool.QueryRow(ctx, "SELECT id, name FROM roles WHERE id=$1", person_id)
|
|
||||||
err = row.Scan(&role.ID, &role.Name)
|
|
||||||
if err != nil {
|
|
||||||
if err == pgx.ErrNoRows {
|
|
||||||
err = fmt.Errorf("not found")
|
|
||||||
statusCode = http.StatusNotFound
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pgErr := err.(*pgconn.PgError)
|
|
||||||
if pgErr.Code == "22P02" {
|
|
||||||
err = fmt.Errorf("%s", pgErr.Message)
|
|
||||||
statusCode = http.StatusBadRequest
|
|
||||||
} else {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
statusCode = http.StatusOK
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func RoleAdd(ctx context.Context, user_id, name string) (role models.Role, statusCode int, err error) {
|
|
||||||
ok, editor := UserAuth(ctx, user_id)
|
|
||||||
if !ok {
|
|
||||||
err = fmt.Errorf("unauthorized")
|
|
||||||
statusCode = http.StatusUnauthorized
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !editor {
|
|
||||||
err = fmt.Errorf("not allowed")
|
|
||||||
statusCode = http.StatusForbidden
|
|
||||||
return
|
|
||||||
}
|
|
||||||
row := connPool.QueryRow(ctx, "INSERT INTO roles (name) VALUES ($1) RETURNING id, name", name)
|
|
||||||
err = row.Scan(&role.ID, &role.Name)
|
|
||||||
if err != nil {
|
|
||||||
pgErr := err.(*pgconn.PgError)
|
|
||||||
if pgErr.Code == "22P02" {
|
|
||||||
err = fmt.Errorf("%s", pgErr.Message)
|
|
||||||
statusCode = http.StatusBadRequest
|
|
||||||
} else if pgErr.Code == "23505" {
|
|
||||||
err = fmt.Errorf("a role with this name already exists")
|
|
||||||
statusCode = http.StatusConflict
|
|
||||||
} else {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
statusCode = http.StatusOK
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func RoleUpdate(ctx context.Context, user_id, role_id string, values map[string]string) (role models.Role, statusCode int, err error) {
|
|
||||||
ok, editor := UserAuth(ctx, user_id)
|
|
||||||
if !ok {
|
|
||||||
err = fmt.Errorf("unauthorized")
|
|
||||||
statusCode = http.StatusUnauthorized
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !editor {
|
|
||||||
err = fmt.Errorf("not allowed")
|
|
||||||
statusCode = http.StatusForbidden
|
|
||||||
return
|
|
||||||
}
|
|
||||||
statusCode, err = transaction(ctx, func(tx pgx.Tx) (statusCode int, err error) {
|
|
||||||
for _, field := range []string{"name"} {
|
|
||||||
value, ok := values[field]
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var commandTag pgconn.CommandTag
|
|
||||||
commandTag, err = tx.Exec(ctx, fmt.Sprintf("UPDATE roles SET %s=NULLIF($2, '') WHERE id=$1", field), role_id, value)
|
|
||||||
if err != nil {
|
|
||||||
pgErr := err.(*pgconn.PgError)
|
|
||||||
if pgErr.Code == "22P02" {
|
|
||||||
err = fmt.Errorf("%s", pgErr.Message)
|
|
||||||
statusCode = http.StatusBadRequest
|
|
||||||
} else if pgErr.Code == "23505" {
|
|
||||||
err = fmt.Errorf("a person with this name already exists")
|
|
||||||
statusCode = http.StatusConflict
|
|
||||||
} else {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if commandTag.RowsAffected() == 0 {
|
|
||||||
err = fmt.Errorf("not found")
|
|
||||||
statusCode = http.StatusNotFound
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
row := tx.QueryRow(ctx, "SELECT id, name FROM roles WHERE id=$1", role_id)
|
|
||||||
err = row.Scan(&role.ID, &role.Name)
|
|
||||||
if err != nil {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
return
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
statusCode = http.StatusOK
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func RoleDelete(ctx context.Context, user_id, role_id string) (statusCode int, err error) {
|
|
||||||
ok, editor := UserAuth(ctx, user_id)
|
|
||||||
if !ok {
|
|
||||||
err = fmt.Errorf("unauthorized")
|
|
||||||
statusCode = http.StatusUnauthorized
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !editor {
|
|
||||||
err = fmt.Errorf("not allowed")
|
|
||||||
statusCode = http.StatusForbidden
|
|
||||||
return
|
|
||||||
}
|
|
||||||
commandTag, err := connPool.Exec(ctx, "DELETE FROM roles WHERE id=$1", role_id)
|
|
||||||
if err != nil {
|
|
||||||
pgErr := err.(*pgconn.PgError)
|
|
||||||
if pgErr.Code == "22P02" {
|
|
||||||
err = fmt.Errorf("%s", pgErr.Message)
|
|
||||||
statusCode = http.StatusBadRequest
|
|
||||||
} else {
|
|
||||||
statusCode = http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if commandTag.RowsAffected() == 0 {
|
|
||||||
err = fmt.Errorf("not found")
|
|
||||||
statusCode = http.StatusNotFound
|
|
||||||
return
|
|
||||||
}
|
|
||||||
statusCode = http.StatusNoContent
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
package db
|
|
||||||
|
|
||||||
import "context"
|
|
||||||
|
|
||||||
func UserLogin(ctx context.Context, login, password string) (user_id string, err error) {
|
|
||||||
row := connPool.QueryRow(ctx, "SELECT id FROM users WHERE login=$1 AND password=crypt($2, password)", login, password)
|
|
||||||
err = row.Scan(&user_id)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func UserAuth(ctx context.Context, user_id string) (ok, editor bool) {
|
|
||||||
row := connPool.QueryRow(ctx, "SELECT editor FROM users WHERE id=$1", user_id)
|
|
||||||
err := row.Scan(&editor)
|
|
||||||
ok = (err == nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@ -1,6 +1,10 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
//#region Objects
|
||||||
|
|
||||||
type Role struct {
|
type Role struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
@ -33,9 +37,8 @@ type Person struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ArtistBrief struct {
|
type ArtistBrief struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
SortName string `json:"sortName"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Artist struct {
|
type Artist struct {
|
||||||
@ -46,15 +49,14 @@ type Artist struct {
|
|||||||
type TrackBrief struct {
|
type TrackBrief struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
SortName string `json:"sortName"`
|
|
||||||
Duration float32 `json:"duration"`
|
Duration float32 `json:"duration"`
|
||||||
ReleaseDate string `json:"release_date"`
|
ReleaseDate string `json:"release_date"`
|
||||||
AcquireDatetime time.Time `json:"acquire_datetime"`
|
AcquireDatetime time.Time `json:"acquire_datetime"`
|
||||||
|
ISRC string `json:"isrc"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Track struct {
|
type Track struct {
|
||||||
TrackBrief
|
TrackBrief
|
||||||
ISRC string `json:"isrc"`
|
|
||||||
Lyrics string `json:"lyrics"`
|
Lyrics string `json:"lyrics"`
|
||||||
Info string `json:"info"`
|
Info string `json:"info"`
|
||||||
}
|
}
|
||||||
@ -70,3 +72,46 @@ type Kiroku struct {
|
|||||||
Alias Alias `json:"alias"`
|
Alias Alias `json:"alias"`
|
||||||
Datetime time.Time `json:"datetime"`
|
Datetime time.Time `json:"datetime"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#endregion Objects
|
||||||
|
|
||||||
|
//#region Sets
|
||||||
|
|
||||||
|
type Pagination struct {
|
||||||
|
Total int `json:"total"`
|
||||||
|
Offset int `json:"offset"`
|
||||||
|
Limit int `json:"limit"`
|
||||||
|
Count int `json:"count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Persons struct {
|
||||||
|
Pagination Pagination `json:"pagination"`
|
||||||
|
Persons []PersonBrief `json:"persons"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Roles struct {
|
||||||
|
Pagination Pagination `json:"pagination"`
|
||||||
|
Roles []Role `json:"roles"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Artists struct {
|
||||||
|
Pagination Pagination `json:"pagination"`
|
||||||
|
Artists []ArtistBrief `json:"artists"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tracks struct {
|
||||||
|
Pagination Pagination `json:"pagination"`
|
||||||
|
Tracks []TrackBrief `json:"tracks"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Aliases struct {
|
||||||
|
Pagination Pagination `json:"pagination"`
|
||||||
|
Aliases []Alias `json:"aliases"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Kirokus struct {
|
||||||
|
Pagination Pagination `json:"pagination"`
|
||||||
|
Kirokus []Kiroku `json:"kirokus"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion Sets
|
||||||
@ -1,38 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
type Pagination struct {
|
|
||||||
Total int `json:"total"`
|
|
||||||
Offset int `json:"offset"`
|
|
||||||
Limit int `json:"limit"`
|
|
||||||
Count int `json:"count"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PersonSlice struct {
|
|
||||||
Pagination Pagination `json:"pagination"`
|
|
||||||
Persons []PersonBrief `json:"persons"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RoleSlice struct {
|
|
||||||
Pagination Pagination `json:"pagination"`
|
|
||||||
Roles []Role `json:"roles"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ArtistSlice struct {
|
|
||||||
Pagination Pagination `json:"pagination"`
|
|
||||||
Artists []ArtistBrief `json:"artists"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TrackSlice struct {
|
|
||||||
Pagination Pagination `json:"pagination"`
|
|
||||||
Tracks []TrackBrief `json:"tracks"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type AliasSlice struct {
|
|
||||||
Pagination Pagination `json:"pagination"`
|
|
||||||
Aliases []Alias `json:"aliases"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type KirokuSlice struct {
|
|
||||||
Pagination Pagination `json:"pagination"`
|
|
||||||
Kirokus []Kiroku `json:"kirokus"`
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user