Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e375e79954 | |||
| 2e2251ee19 | |||
| 568230b966 |
@@ -1042,8 +1042,8 @@ func (s *Store) ListSSHAccessProfilesForUser(userID string) ([]models.SSHAccessP
|
|||||||
p.owner_scope = ?
|
p.owner_scope = ?
|
||||||
AND p.enabled = 1
|
AND p.enabled = 1
|
||||||
AND s.enabled = 1
|
AND s.enabled = 1
|
||||||
AND (p.valid_after = 0 OR p.valid_after <= strftime('%s','now'))
|
AND (p.valid_after = 0 OR p.valid_after <= CAST(strftime('%s','now') AS INTEGER))
|
||||||
AND (p.valid_before = 0 OR p.valid_before >= strftime('%s','now'))
|
AND (p.valid_before = 0 OR p.valid_before >= CAST(strftime('%s','now') AS INTEGER))
|
||||||
AND (
|
AND (
|
||||||
(t.target_type = 'user' AND tu.public_id = ?)
|
(t.target_type = 'user' AND tu.public_id = ?)
|
||||||
OR
|
OR
|
||||||
@@ -1234,8 +1234,8 @@ func (s *Store) GetSSHAccessProfileForUser(userID string, id string) (models.SSH
|
|||||||
p.owner_scope = ?
|
p.owner_scope = ?
|
||||||
AND p.enabled = 1
|
AND p.enabled = 1
|
||||||
AND s.enabled = 1
|
AND s.enabled = 1
|
||||||
AND (p.valid_after = 0 OR p.valid_after <= strftime('%s','now'))
|
AND (p.valid_after = 0 OR p.valid_after <= CAST(strftime('%s','now') AS INTEGER))
|
||||||
AND (p.valid_before = 0 OR p.valid_before >= strftime('%s','now'))
|
AND (p.valid_before = 0 OR p.valid_before >= CAST(strftime('%s','now') AS INTEGER))
|
||||||
AND (
|
AND (
|
||||||
(t.target_type = 'user' AND tu.public_id = ?)
|
(t.target_type = 'user' AND tu.public_id = ?)
|
||||||
OR
|
OR
|
||||||
|
|||||||
+68
-155
@@ -11,7 +11,6 @@ import "codit/internal/util"
|
|||||||
func (s *Store) CreateUser(user models.User, passwordHash string) (models.User, error) {
|
func (s *Store) CreateUser(user models.User, passwordHash string) (models.User, error) {
|
||||||
var id string
|
var id string
|
||||||
var err error
|
var err error
|
||||||
var now time.Time
|
|
||||||
var nowUnix int64
|
var nowUnix int64
|
||||||
if user.ID == "" {
|
if user.ID == "" {
|
||||||
id, err = util.NewID()
|
id, err = util.NewID()
|
||||||
@@ -20,44 +19,39 @@ func (s *Store) CreateUser(user models.User, passwordHash string) (models.User,
|
|||||||
}
|
}
|
||||||
user.ID = id
|
user.ID = id
|
||||||
}
|
}
|
||||||
now = time.Now().UTC()
|
nowUnix = time.Now().UTC().Unix()
|
||||||
nowUnix = now.Unix()
|
|
||||||
user.CreatedAt = nowUnix
|
user.CreatedAt = nowUnix
|
||||||
user.UpdatedAt = nowUnix
|
user.UpdatedAt = nowUnix
|
||||||
_, err = s.Exec(`
|
_, err = s.Exec(`
|
||||||
INSERT INTO users (public_id, username, display_name, email, password_hash, is_admin, disabled, auth_provider_id, totp_required, external_subject, created_at, updated_at)
|
INSERT INTO users (public_id, username, display_name, email, password_hash, is_admin, disabled, auth_provider_id, totp_required, external_subject, created_at, updated_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, CASE WHEN ? = '' THEN NULL ELSE (SELECT id FROM auth_providers WHERE public_id = ?) END, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, CASE WHEN ? = '' THEN NULL ELSE (SELECT id FROM auth_providers WHERE public_id = ?) END, ?, ?, ?, ?)
|
||||||
`, user.ID, user.Username, user.DisplayName, user.Email, passwordHash, user.IsAdmin, user.Disabled, user.AuthProviderID, user.AuthProviderID, user.TOTPRequired, user.ExternalSubject, now, now)
|
`, user.ID, user.Username, user.DisplayName, user.Email, passwordHash, user.IsAdmin, user.Disabled, user.AuthProviderID, user.AuthProviderID, user.TOTPRequired, user.ExternalSubject, nowUnix, nowUnix)
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) UpdateUser(user models.User) error {
|
func (s *Store) UpdateUser(user models.User) error {
|
||||||
var err error
|
var err error
|
||||||
var now time.Time
|
|
||||||
var nowUnix int64
|
var nowUnix int64
|
||||||
now = time.Now().UTC()
|
nowUnix = time.Now().UTC().Unix()
|
||||||
nowUnix = now.Unix()
|
|
||||||
user.UpdatedAt = nowUnix
|
user.UpdatedAt = nowUnix
|
||||||
_, err = s.Exec(`UPDATE users SET display_name = ?, email = ?, is_admin = ?, disabled = ?, totp_required = ?, updated_at = ? WHERE public_id = ?`,
|
_, err = s.Exec(`UPDATE users SET display_name = ?, email = ?, is_admin = ?, disabled = ?, totp_required = ?, updated_at = ? WHERE public_id = ?`,
|
||||||
user.DisplayName, user.Email, user.IsAdmin, user.Disabled, user.TOTPRequired, now, user.ID)
|
user.DisplayName, user.Email, user.IsAdmin, user.Disabled, user.TOTPRequired, nowUnix, user.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) UpdateUserWithPassword(user models.User, passwordHash string) error {
|
func (s *Store) UpdateUserWithPassword(user models.User, passwordHash string) error {
|
||||||
var err error
|
var err error
|
||||||
var now time.Time
|
|
||||||
var nowUnix int64
|
var nowUnix int64
|
||||||
var tx *sql.Tx
|
var tx *sql.Tx
|
||||||
var owned bool
|
var owned bool
|
||||||
now = time.Now().UTC()
|
nowUnix = time.Now().UTC().Unix()
|
||||||
nowUnix = now.Unix()
|
|
||||||
user.UpdatedAt = nowUnix
|
user.UpdatedAt = nowUnix
|
||||||
tx, owned, err = s.begin()
|
tx, owned, err = s.begin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = tx.Exec(`UPDATE users SET display_name = ?, email = ?, is_admin = ?, disabled = ?, totp_required = ?, password_hash = ?, updated_at = ? WHERE public_id = ?`,
|
_, err = tx.Exec(`UPDATE users SET display_name = ?, email = ?, is_admin = ?, disabled = ?, totp_required = ?, password_hash = ?, updated_at = ? WHERE public_id = ?`,
|
||||||
user.DisplayName, user.Email, user.IsAdmin, user.Disabled, user.TOTPRequired, passwordHash, now, user.ID)
|
user.DisplayName, user.Email, user.IsAdmin, user.Disabled, user.TOTPRequired, passwordHash, nowUnix, user.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rollbackIfOwned(tx, owned)
|
rollbackIfOwned(tx, owned)
|
||||||
return err
|
return err
|
||||||
@@ -71,23 +65,19 @@ func (s *Store) UpdateUserWithPassword(user models.User, passwordHash string) er
|
|||||||
|
|
||||||
func (s *Store) SetUserPassword(userID, passwordHash string) error {
|
func (s *Store) SetUserPassword(userID, passwordHash string) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.Exec(`UPDATE users SET password_hash = ?, updated_at = ? WHERE public_id = ?`, passwordHash, time.Now().UTC(), userID)
|
_, err = s.Exec(`UPDATE users SET password_hash = ?, updated_at = ? WHERE public_id = ?`, passwordHash, time.Now().UTC().Unix(), userID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) GetUserByID(id string) (models.User, error) {
|
func (s *Store) GetUserByID(id string) (models.User, error) {
|
||||||
var user models.User
|
var user models.User
|
||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var created time.Time
|
|
||||||
var updated time.Time
|
|
||||||
var err error
|
var err error
|
||||||
row = s.QueryRow(`SELECT u.public_id, u.username, u.display_name, u.email, u.is_admin, u.disabled, COALESCE(ap.public_id, ''), COALESCE(t.enabled, 0), u.totp_required, u.created_at, u.updated_at FROM users u LEFT JOIN auth_providers ap ON ap.id = u.auth_provider_id LEFT JOIN user_totp t ON t.user_id = u.id WHERE u.public_id = ?`, id)
|
row = s.QueryRow(`SELECT u.public_id, u.username, u.display_name, u.email, u.is_admin, u.disabled, COALESCE(ap.public_id, ''), COALESCE(t.enabled, 0), u.totp_required, u.created_at, u.updated_at FROM users u LEFT JOIN auth_providers ap ON ap.id = u.auth_provider_id LEFT JOIN user_totp t ON t.user_id = u.id WHERE u.public_id = ?`, id)
|
||||||
err = row.Scan(&user.ID, &user.Username, &user.DisplayName, &user.Email, &user.IsAdmin, &user.Disabled, &user.AuthProviderID, &user.TOTPEnabled, &user.TOTPRequired, &created, &updated)
|
err = row.Scan(&user.ID, &user.Username, &user.DisplayName, &user.Email, &user.IsAdmin, &user.Disabled, &user.AuthProviderID, &user.TOTPEnabled, &user.TOTPRequired, &user.CreatedAt, &user.UpdatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
user.CreatedAt = created.Unix()
|
|
||||||
user.UpdatedAt = updated.Unix()
|
|
||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,15 +86,11 @@ func (s *Store) GetUserByUsername(username string) (models.User, string, error)
|
|||||||
var passwordHash sql.NullString
|
var passwordHash sql.NullString
|
||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var err error
|
var err error
|
||||||
var created time.Time
|
|
||||||
var updated time.Time
|
|
||||||
row = s.QueryRow(`SELECT u.public_id, u.username, u.display_name, u.email, u.is_admin, u.disabled, COALESCE(ap.public_id, ''), u.password_hash, COALESCE(t.enabled, 0), u.totp_required, u.created_at, u.updated_at FROM users u LEFT JOIN auth_providers ap ON ap.id = u.auth_provider_id LEFT JOIN user_totp t ON t.user_id = u.id WHERE u.username = ?`, username)
|
row = s.QueryRow(`SELECT u.public_id, u.username, u.display_name, u.email, u.is_admin, u.disabled, COALESCE(ap.public_id, ''), u.password_hash, COALESCE(t.enabled, 0), u.totp_required, u.created_at, u.updated_at FROM users u LEFT JOIN auth_providers ap ON ap.id = u.auth_provider_id LEFT JOIN user_totp t ON t.user_id = u.id WHERE u.username = ?`, username)
|
||||||
err = row.Scan(&user.ID, &user.Username, &user.DisplayName, &user.Email, &user.IsAdmin, &user.Disabled, &user.AuthProviderID, &passwordHash, &user.TOTPEnabled, &user.TOTPRequired, &created, &updated)
|
err = row.Scan(&user.ID, &user.Username, &user.DisplayName, &user.Email, &user.IsAdmin, &user.Disabled, &user.AuthProviderID, &passwordHash, &user.TOTPEnabled, &user.TOTPRequired, &user.CreatedAt, &user.UpdatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return user, passwordHash.String, err
|
return user, passwordHash.String, err
|
||||||
}
|
}
|
||||||
user.CreatedAt = created.Unix()
|
|
||||||
user.UpdatedAt = updated.Unix()
|
|
||||||
return user, passwordHash.String, nil
|
return user, passwordHash.String, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,20 +99,16 @@ func (s *Store) ListUsers() ([]models.User, error) {
|
|||||||
var err error
|
var err error
|
||||||
var users []models.User
|
var users []models.User
|
||||||
var u models.User
|
var u models.User
|
||||||
var created time.Time
|
|
||||||
var updated time.Time
|
|
||||||
rows, err = s.Query(`SELECT u.public_id, u.username, u.display_name, u.email, u.is_admin, u.disabled, COALESCE(ap.public_id, ''), COALESCE(t.enabled, 0), u.totp_required, u.created_at, u.updated_at FROM users u LEFT JOIN auth_providers ap ON ap.id = u.auth_provider_id LEFT JOIN user_totp t ON t.user_id = u.id ORDER BY u.username`)
|
rows, err = s.Query(`SELECT u.public_id, u.username, u.display_name, u.email, u.is_admin, u.disabled, COALESCE(ap.public_id, ''), COALESCE(t.enabled, 0), u.totp_required, u.created_at, u.updated_at FROM users u LEFT JOIN auth_providers ap ON ap.id = u.auth_provider_id LEFT JOIN user_totp t ON t.user_id = u.id ORDER BY u.username`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
err = rows.Scan(&u.ID, &u.Username, &u.DisplayName, &u.Email, &u.IsAdmin, &u.Disabled, &u.AuthProviderID, &u.TOTPEnabled, &u.TOTPRequired, &created, &updated)
|
err = rows.Scan(&u.ID, &u.Username, &u.DisplayName, &u.Email, &u.IsAdmin, &u.Disabled, &u.AuthProviderID, &u.TOTPEnabled, &u.TOTPRequired, &u.CreatedAt, &u.UpdatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
u.CreatedAt = created.Unix()
|
|
||||||
u.UpdatedAt = updated.Unix()
|
|
||||||
users = append(users, u)
|
users = append(users, u)
|
||||||
}
|
}
|
||||||
return users, rows.Err()
|
return users, rows.Err()
|
||||||
@@ -167,8 +149,6 @@ func (s *Store) DeleteUser(id string) error {
|
|||||||
func (s *Store) GetUserByProviderAndSub(providerPublicID string, sub string) (models.User, error) {
|
func (s *Store) GetUserByProviderAndSub(providerPublicID string, sub string) (models.User, error) {
|
||||||
var user models.User
|
var user models.User
|
||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var created time.Time
|
|
||||||
var updated time.Time
|
|
||||||
var err error
|
var err error
|
||||||
row = s.QueryRow(`
|
row = s.QueryRow(`
|
||||||
SELECT u.public_id, u.username, u.display_name, u.email, u.is_admin, u.disabled,
|
SELECT u.public_id, u.username, u.display_name, u.email, u.is_admin, u.disabled,
|
||||||
@@ -179,12 +159,10 @@ func (s *Store) GetUserByProviderAndSub(providerPublicID string, sub string) (mo
|
|||||||
WHERE ap.public_id = ? AND u.external_subject = ?
|
WHERE ap.public_id = ? AND u.external_subject = ?
|
||||||
`, strings.TrimSpace(providerPublicID), strings.TrimSpace(sub))
|
`, strings.TrimSpace(providerPublicID), strings.TrimSpace(sub))
|
||||||
err = row.Scan(&user.ID, &user.Username, &user.DisplayName, &user.Email, &user.IsAdmin, &user.Disabled,
|
err = row.Scan(&user.ID, &user.Username, &user.DisplayName, &user.Email, &user.IsAdmin, &user.Disabled,
|
||||||
&user.AuthProviderID, &user.ExternalSubject, &user.TOTPEnabled, &user.TOTPRequired, &created, &updated)
|
&user.AuthProviderID, &user.ExternalSubject, &user.TOTPEnabled, &user.TOTPRequired, &user.CreatedAt, &user.UpdatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
user.CreatedAt = created.Unix()
|
|
||||||
user.UpdatedAt = updated.Unix()
|
|
||||||
return user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,24 +346,20 @@ func splitCSVValue(value string) []string {
|
|||||||
|
|
||||||
func (s *Store) SetUserDisabled(id string, disabled bool) error {
|
func (s *Store) SetUserDisabled(id string, disabled bool) error {
|
||||||
var err error
|
var err error
|
||||||
var now time.Time
|
_, err = s.Exec(`UPDATE users SET disabled = ?, updated_at = ? WHERE public_id = ?`, disabled, time.Now().UTC().Unix(), id)
|
||||||
now = time.Now().UTC()
|
|
||||||
_, err = s.Exec(`UPDATE users SET disabled = ?, updated_at = ? WHERE public_id = ?`, disabled, now, id)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) CreateAPIKey(userID string, name string, tokenHash string, prefix string, expiresAt int64) (models.APIKey, error) {
|
func (s *Store) CreateAPIKey(userID string, name string, tokenHash string, prefix string, expiresAt int64) (models.APIKey, error) {
|
||||||
var key models.APIKey
|
var key models.APIKey
|
||||||
var err error
|
var err error
|
||||||
var now time.Time
|
|
||||||
var nowUnix int64
|
var nowUnix int64
|
||||||
var id string
|
var id string
|
||||||
id, err = util.NewID()
|
id, err = util.NewID()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return key, err
|
return key, err
|
||||||
}
|
}
|
||||||
now = time.Now().UTC()
|
nowUnix = time.Now().UTC().Unix()
|
||||||
nowUnix = now.Unix()
|
|
||||||
key = models.APIKey{
|
key = models.APIKey{
|
||||||
ID: id,
|
ID: id,
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
@@ -604,19 +578,14 @@ func (s *Store) GetUserByAPIKeyHash(tokenHash string) (models.User, error) {
|
|||||||
var tx *sql.Tx
|
var tx *sql.Tx
|
||||||
var owned bool
|
var owned bool
|
||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var created time.Time
|
|
||||||
var updated time.Time
|
|
||||||
var keyID int64
|
var keyID int64
|
||||||
var now time.Time
|
|
||||||
var nowUnix int64
|
var nowUnix int64
|
||||||
var err error
|
var err error
|
||||||
var currentUnix int64
|
|
||||||
tx, owned, err = s.begin()
|
tx, owned, err = s.begin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
now = time.Now().UTC()
|
nowUnix = time.Now().UTC().Unix()
|
||||||
currentUnix = now.Unix()
|
|
||||||
row = tx.QueryRow(`
|
row = tx.QueryRow(`
|
||||||
SELECT u.public_id, u.username, u.display_name, u.email, u.is_admin, u.disabled, COALESCE(ap.public_id, ''), u.created_at, u.updated_at, k.id
|
SELECT u.public_id, u.username, u.display_name, u.email, u.is_admin, u.disabled, COALESCE(ap.public_id, ''), u.created_at, u.updated_at, k.id
|
||||||
FROM api_keys k
|
FROM api_keys k
|
||||||
@@ -627,16 +596,13 @@ func (s *Store) GetUserByAPIKeyHash(tokenHash string) (models.User, error) {
|
|||||||
AND k.disabled = 0
|
AND k.disabled = 0
|
||||||
AND (k.expires_at = 0 OR k.expires_at > ?)
|
AND (k.expires_at = 0 OR k.expires_at > ?)
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
`, tokenHash, currentUnix)
|
`, tokenHash, nowUnix)
|
||||||
err = row.Scan(&user.ID, &user.Username, &user.DisplayName, &user.Email, &user.IsAdmin, &user.Disabled, &user.AuthProviderID, &created, &updated, &keyID)
|
err = row.Scan(&user.ID, &user.Username, &user.DisplayName, &user.Email, &user.IsAdmin, &user.Disabled, &user.AuthProviderID, &user.CreatedAt, &user.UpdatedAt, &keyID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rollbackIfOwned(tx, owned)
|
rollbackIfOwned(tx, owned)
|
||||||
return user, err
|
return user, err
|
||||||
}
|
}
|
||||||
user.CreatedAt = created.Unix()
|
nowUnix = time.Now().UTC().Unix()
|
||||||
user.UpdatedAt = updated.Unix()
|
|
||||||
now = time.Now().UTC()
|
|
||||||
nowUnix = now.Unix()
|
|
||||||
_, err = tx.Exec(`UPDATE api_keys SET last_used_at = ? WHERE id = ?`, nowUnix, keyID)
|
_, err = tx.Exec(`UPDATE api_keys SET last_used_at = ? WHERE id = ?`, nowUnix, keyID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rollbackIfOwned(tx, owned)
|
rollbackIfOwned(tx, owned)
|
||||||
@@ -653,7 +619,7 @@ func (s *Store) CreateSession(userID string, token string, expiresAt time.Time,
|
|||||||
var err error
|
var err error
|
||||||
_, err = s.Exec(`INSERT INTO sessions (id, user_id, token, expires_at, created_at, totp_verified)
|
_, err = s.Exec(`INSERT INTO sessions (id, user_id, token, expires_at, created_at, totp_verified)
|
||||||
VALUES (?, (SELECT id FROM users WHERE public_id = ?), ?, ?, ?, ?)`,
|
VALUES (?, (SELECT id FROM users WHERE public_id = ?), ?, ?, ?, ?)`,
|
||||||
mustID(), userID, token, expiresAt, time.Now().UTC(), totpVerified)
|
mustID(), userID, token, expiresAt.Unix(), time.Now().UTC().Unix(), totpVerified)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -671,18 +637,16 @@ func (s *Store) DeleteSession(token string) error {
|
|||||||
|
|
||||||
func (s *Store) DeleteExpiredSessions(now time.Time) error {
|
func (s *Store) DeleteExpiredSessions(now time.Time) error {
|
||||||
var err error
|
var err error
|
||||||
_, err = s.Exec(`DELETE FROM sessions WHERE expires_at < ?`, now.UTC())
|
_, err = s.Exec(`DELETE FROM sessions WHERE expires_at < ?`, now.UTC().Unix())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) GetSessionUser(token string) (models.User, time.Time, bool, error) {
|
func (s *Store) GetSessionUser(token string) (models.User, time.Time, bool, error) {
|
||||||
var user models.User
|
var user models.User
|
||||||
var expires time.Time
|
var expiresUnix int64
|
||||||
var totpVerified bool
|
var totpVerified bool
|
||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var err error
|
var err error
|
||||||
var created time.Time
|
|
||||||
var updated time.Time
|
|
||||||
row = s.QueryRow(`
|
row = s.QueryRow(`
|
||||||
SELECT u.public_id, u.username, u.display_name, u.email, u.is_admin, u.disabled, COALESCE(ap.public_id, ''), COALESCE(t.enabled, 0), u.totp_required,
|
SELECT u.public_id, u.username, u.display_name, u.email, u.is_admin, u.disabled, COALESCE(ap.public_id, ''), COALESCE(t.enabled, 0), u.totp_required,
|
||||||
(u.totp_required OR EXISTS (
|
(u.totp_required OR EXISTS (
|
||||||
@@ -698,20 +662,17 @@ func (s *Store) GetSessionUser(token string) (models.User, time.Time, bool, erro
|
|||||||
LEFT JOIN auth_providers ap ON ap.id = u.auth_provider_id
|
LEFT JOIN auth_providers ap ON ap.id = u.auth_provider_id
|
||||||
WHERE s.token = ? AND u.disabled = 0
|
WHERE s.token = ? AND u.disabled = 0
|
||||||
`, token)
|
`, token)
|
||||||
err = row.Scan(&user.ID, &user.Username, &user.DisplayName, &user.Email, &user.IsAdmin, &user.Disabled, &user.AuthProviderID, &user.TOTPEnabled, &user.TOTPRequired, &user.TOTPEffectiveRequired, &totpVerified, &created, &updated, &expires)
|
err = row.Scan(&user.ID, &user.Username, &user.DisplayName, &user.Email, &user.IsAdmin, &user.Disabled, &user.AuthProviderID, &user.TOTPEnabled, &user.TOTPRequired, &user.TOTPEffectiveRequired, &totpVerified, &user.CreatedAt, &user.UpdatedAt, &expiresUnix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return user, time.Time{}, false, err
|
return user, time.Time{}, false, err
|
||||||
}
|
}
|
||||||
user.CreatedAt = created.Unix()
|
|
||||||
user.UpdatedAt = updated.Unix()
|
|
||||||
user.TOTPSetupRequired = user.TOTPEffectiveRequired && !user.TOTPEnabled
|
user.TOTPSetupRequired = user.TOTPEffectiveRequired && !user.TOTPEnabled
|
||||||
return user, expires, totpVerified, nil
|
return user, time.Unix(expiresUnix, 0).UTC(), totpVerified, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) CreateProject(project models.Project) (models.Project, error) {
|
func (s *Store) CreateProject(project models.Project) (models.Project, error) {
|
||||||
var id string
|
var id string
|
||||||
var err error
|
var err error
|
||||||
var now time.Time
|
|
||||||
var nowUnix int64
|
var nowUnix int64
|
||||||
var tx *sql.Tx
|
var tx *sql.Tx
|
||||||
var owned bool
|
var owned bool
|
||||||
@@ -722,8 +683,7 @@ func (s *Store) CreateProject(project models.Project) (models.Project, error) {
|
|||||||
}
|
}
|
||||||
project.ID = id
|
project.ID = id
|
||||||
}
|
}
|
||||||
now = time.Now().UTC()
|
nowUnix = time.Now().UTC().Unix()
|
||||||
nowUnix = now.Unix()
|
|
||||||
project.CreatedAt = nowUnix
|
project.CreatedAt = nowUnix
|
||||||
project.UpdatedAt = nowUnix
|
project.UpdatedAt = nowUnix
|
||||||
if project.UpdatedBy == "" {
|
if project.UpdatedBy == "" {
|
||||||
@@ -734,10 +694,10 @@ func (s *Store) CreateProject(project models.Project) (models.Project, error) {
|
|||||||
return project, err
|
return project, err
|
||||||
}
|
}
|
||||||
if project.HomePage == "" {
|
if project.HomePage == "" {
|
||||||
project.HomePage = "info"
|
project.HomePage = "settings"
|
||||||
}
|
}
|
||||||
_, err = tx.Exec(`INSERT INTO projects (public_id, slug, name, description, home_page, created_by, updated_by, created_at, updated_at, created_at_unix, updated_at_unix)
|
_, err = tx.Exec(`INSERT INTO projects (public_id, slug, name, description, home_page, created_by, updated_by, created_at, updated_at)
|
||||||
VALUES (?, ?, ?, ?, ?, (SELECT id FROM users WHERE public_id = ?), (SELECT id FROM users WHERE public_id = ?), ?, ?, ?, ?)`,
|
VALUES (?, ?, ?, ?, ?, (SELECT id FROM users WHERE public_id = ?), (SELECT id FROM users WHERE public_id = ?), ?, ?)`,
|
||||||
project.ID,
|
project.ID,
|
||||||
project.Slug,
|
project.Slug,
|
||||||
project.Name,
|
project.Name,
|
||||||
@@ -745,8 +705,6 @@ func (s *Store) CreateProject(project models.Project) (models.Project, error) {
|
|||||||
project.HomePage,
|
project.HomePage,
|
||||||
project.CreatedBy,
|
project.CreatedBy,
|
||||||
project.UpdatedBy,
|
project.UpdatedBy,
|
||||||
now,
|
|
||||||
now,
|
|
||||||
project.CreatedAt,
|
project.CreatedAt,
|
||||||
project.UpdatedAt,
|
project.UpdatedAt,
|
||||||
)
|
)
|
||||||
@@ -771,16 +729,15 @@ func (s *Store) CreateProject(project models.Project) (models.Project, error) {
|
|||||||
func (s *Store) UpdateProject(project models.Project) error {
|
func (s *Store) UpdateProject(project models.Project) error {
|
||||||
var err error
|
var err error
|
||||||
if project.HomePage == "" {
|
if project.HomePage == "" {
|
||||||
project.HomePage = "info"
|
project.HomePage = "settings"
|
||||||
}
|
}
|
||||||
_, err = s.Exec(`UPDATE projects SET slug = ?, name = ?, description = ?, home_page = ?, updated_at = ?, updated_by = (SELECT id FROM users WHERE public_id = ?), updated_at_unix = ? WHERE public_id = ?`,
|
_, err = s.Exec(`UPDATE projects SET slug = ?, name = ?, description = ?, home_page = ?, updated_at = ?, updated_by = (SELECT id FROM users WHERE public_id = ?) WHERE public_id = ?`,
|
||||||
project.Slug,
|
project.Slug,
|
||||||
project.Name,
|
project.Name,
|
||||||
project.Description,
|
project.Description,
|
||||||
project.HomePage,
|
project.HomePage,
|
||||||
time.Unix(project.UpdatedAt, 0).UTC(),
|
|
||||||
project.UpdatedBy,
|
|
||||||
project.UpdatedAt,
|
project.UpdatedAt,
|
||||||
|
project.UpdatedBy,
|
||||||
project.ID,
|
project.ID,
|
||||||
)
|
)
|
||||||
return err
|
return err
|
||||||
@@ -793,7 +750,7 @@ func (s *Store) GetProject(id string) (models.Project, error) {
|
|||||||
SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
c.public_id, u.public_id,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at, p.updated_at
|
||||||
FROM projects p
|
FROM projects p
|
||||||
LEFT JOIN users c ON c.id = p.created_by
|
LEFT JOIN users c ON c.id = p.created_by
|
||||||
LEFT JOIN users u ON u.id = p.updated_by
|
LEFT JOIN users u ON u.id = p.updated_by
|
||||||
@@ -822,7 +779,7 @@ func (s *Store) GetProjectBySlug(slug string) (models.Project, error) {
|
|||||||
SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
c.public_id, u.public_id,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at, p.updated_at
|
||||||
FROM projects p
|
FROM projects p
|
||||||
LEFT JOIN users c ON c.id = p.created_by
|
LEFT JOIN users c ON c.id = p.created_by
|
||||||
LEFT JOIN users u ON u.id = p.updated_by
|
LEFT JOIN users u ON u.id = p.updated_by
|
||||||
@@ -856,7 +813,7 @@ func (s *Store) ListProjects() ([]models.Project, error) {
|
|||||||
SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
c.public_id, u.public_id,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at, p.updated_at
|
||||||
FROM projects p
|
FROM projects p
|
||||||
LEFT JOIN users c ON c.id = p.created_by
|
LEFT JOIN users c ON c.id = p.created_by
|
||||||
LEFT JOIN users u ON u.id = p.updated_by
|
LEFT JOIN users u ON u.id = p.updated_by
|
||||||
@@ -897,7 +854,7 @@ func (s *Store) ListProjectsForUser(userID string) ([]models.Project, error) {
|
|||||||
SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
c.public_id, u.public_id,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at, p.updated_at
|
||||||
FROM projects p
|
FROM projects p
|
||||||
LEFT JOIN users c ON c.id = p.created_by
|
LEFT JOIN users c ON c.id = p.created_by
|
||||||
LEFT JOIN users u ON u.id = p.updated_by
|
LEFT JOIN users u ON u.id = p.updated_by
|
||||||
@@ -962,7 +919,7 @@ func (s *Store) ListProjectsForPrincipal(principalID string) ([]models.Project,
|
|||||||
SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
c.public_id, u.public_id,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at, p.updated_at
|
||||||
FROM projects p
|
FROM projects p
|
||||||
LEFT JOIN users c ON c.id = p.created_by
|
LEFT JOIN users c ON c.id = p.created_by
|
||||||
LEFT JOIN users u ON u.id = p.updated_by
|
LEFT JOIN users u ON u.id = p.updated_by
|
||||||
@@ -1017,7 +974,7 @@ func (s *Store) ListProjectsFiltered(limit int, offset int, query string) ([]mod
|
|||||||
`SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
`SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
c.public_id, u.public_id,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at, p.updated_at
|
||||||
FROM projects p
|
FROM projects p
|
||||||
LEFT JOIN users c ON c.id = p.created_by
|
LEFT JOIN users c ON c.id = p.created_by
|
||||||
LEFT JOIN users u ON u.id = p.updated_by
|
LEFT JOIN users u ON u.id = p.updated_by
|
||||||
@@ -1030,7 +987,7 @@ func (s *Store) ListProjectsFiltered(limit int, offset int, query string) ([]mod
|
|||||||
`SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
`SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
c.public_id, u.public_id,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at, p.updated_at
|
||||||
FROM projects p
|
FROM projects p
|
||||||
LEFT JOIN users c ON c.id = p.created_by
|
LEFT JOIN users c ON c.id = p.created_by
|
||||||
LEFT JOIN users u ON u.id = p.updated_by
|
LEFT JOIN users u ON u.id = p.updated_by
|
||||||
@@ -1084,7 +1041,7 @@ func (s *Store) ListProjectsFilteredForUser(userID string, limit int, offset int
|
|||||||
`SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
`SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
c.public_id, u.public_id,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at, p.updated_at
|
||||||
FROM projects p
|
FROM projects p
|
||||||
LEFT JOIN users c ON c.id = p.created_by
|
LEFT JOIN users c ON c.id = p.created_by
|
||||||
LEFT JOIN users u ON u.id = p.updated_by
|
LEFT JOIN users u ON u.id = p.updated_by
|
||||||
@@ -1122,7 +1079,7 @@ func (s *Store) ListProjectsFilteredForUser(userID string, limit int, offset int
|
|||||||
`SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
`SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
c.public_id, u.public_id,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at, p.updated_at
|
||||||
FROM projects p
|
FROM projects p
|
||||||
LEFT JOIN users c ON c.id = p.created_by
|
LEFT JOIN users c ON c.id = p.created_by
|
||||||
LEFT JOIN users u ON u.id = p.updated_by
|
LEFT JOIN users u ON u.id = p.updated_by
|
||||||
@@ -1201,7 +1158,7 @@ func (s *Store) ListProjectsFilteredForPrincipal(principalID string, limit int,
|
|||||||
`SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
`SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
c.public_id, u.public_id,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at, p.updated_at
|
||||||
FROM projects p
|
FROM projects p
|
||||||
LEFT JOIN users c ON c.id = p.created_by
|
LEFT JOIN users c ON c.id = p.created_by
|
||||||
LEFT JOIN users u ON u.id = p.updated_by
|
LEFT JOIN users u ON u.id = p.updated_by
|
||||||
@@ -1222,7 +1179,7 @@ func (s *Store) ListProjectsFilteredForPrincipal(principalID string, limit int,
|
|||||||
`SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
`SELECT p.public_id, p.slug, p.name, p.description, p.home_page,
|
||||||
c.public_id, u.public_id,
|
c.public_id, u.public_id,
|
||||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||||
p.created_at_unix, p.updated_at_unix
|
p.created_at, p.updated_at
|
||||||
FROM projects p
|
FROM projects p
|
||||||
LEFT JOIN users c ON c.id = p.created_by
|
LEFT JOIN users c ON c.id = p.created_by
|
||||||
LEFT JOIN users u ON u.id = p.updated_by
|
LEFT JOIN users u ON u.id = p.updated_by
|
||||||
@@ -1497,7 +1454,6 @@ func (s *Store) GetProjectMemberRole(projectID, userID string) (string, error) {
|
|||||||
func (s *Store) CreateRepo(repo models.Repo) (models.Repo, error) {
|
func (s *Store) CreateRepo(repo models.Repo) (models.Repo, error) {
|
||||||
var id string
|
var id string
|
||||||
var err error
|
var err error
|
||||||
var now time.Time
|
|
||||||
var nowUnix int64
|
var nowUnix int64
|
||||||
if repo.ID == "" {
|
if repo.ID == "" {
|
||||||
id, err = util.NewID()
|
id, err = util.NewID()
|
||||||
@@ -1506,12 +1462,11 @@ func (s *Store) CreateRepo(repo models.Repo) (models.Repo, error) {
|
|||||||
}
|
}
|
||||||
repo.ID = id
|
repo.ID = id
|
||||||
}
|
}
|
||||||
now = time.Now().UTC()
|
nowUnix = time.Now().UTC().Unix()
|
||||||
nowUnix = now.Unix()
|
|
||||||
repo.CreatedAt = nowUnix
|
repo.CreatedAt = nowUnix
|
||||||
_, err = s.Exec(`INSERT INTO repos (public_id, project_id, name, type, path, created_by, created_at)
|
_, err = s.Exec(`INSERT INTO repos (public_id, project_id, name, type, path, created_by, created_at)
|
||||||
VALUES (?, (SELECT id FROM projects WHERE public_id = ?), ?, ?, ?, (SELECT id FROM users WHERE public_id = ?), ?)`,
|
VALUES (?, (SELECT id FROM projects WHERE public_id = ?), ?, ?, ?, (SELECT id FROM users WHERE public_id = ?), ?)`,
|
||||||
repo.ID, repo.ProjectID, repo.Name, repo.Type, repo.Path, repo.CreatedBy, now)
|
repo.ID, repo.ProjectID, repo.Name, repo.Type, repo.Path, repo.CreatedBy, nowUnix)
|
||||||
return repo, err
|
return repo, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1532,18 +1487,16 @@ func (s *Store) RepoNameExists(projectID string, name string, repoType string) (
|
|||||||
func (s *Store) GetRepo(id string) (models.Repo, error) {
|
func (s *Store) GetRepo(id string) (models.Repo, error) {
|
||||||
var repo models.Repo
|
var repo models.Repo
|
||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var created time.Time
|
|
||||||
var err error
|
var err error
|
||||||
row = s.QueryRow(`SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at
|
row = s.QueryRow(`SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at
|
||||||
FROM repos r
|
FROM repos r
|
||||||
JOIN projects p ON p.id = r.project_id
|
JOIN projects p ON p.id = r.project_id
|
||||||
JOIN users u ON u.id = r.created_by
|
JOIN users u ON u.id = r.created_by
|
||||||
WHERE r.public_id = ?`, id)
|
WHERE r.public_id = ?`, id)
|
||||||
err = row.Scan(&repo.ID, &repo.ProjectID, &repo.Name, &repo.Type, &repo.Path, &repo.CreatedBy, &created)
|
err = row.Scan(&repo.ID, &repo.ProjectID, &repo.Name, &repo.Type, &repo.Path, &repo.CreatedBy, &repo.CreatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return repo, err
|
return repo, err
|
||||||
}
|
}
|
||||||
repo.CreatedAt = created.Unix()
|
|
||||||
return repo, nil
|
return repo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1567,7 +1520,6 @@ func (s *Store) GetRepoByProjectNameType(projectID string, name string, repoType
|
|||||||
var repo models.Repo
|
var repo models.Repo
|
||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var err error
|
var err error
|
||||||
var created time.Time
|
|
||||||
row = s.QueryRow(`SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at
|
row = s.QueryRow(`SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at
|
||||||
FROM repos r
|
FROM repos r
|
||||||
JOIN projects p ON p.id = r.project_id
|
JOIN projects p ON p.id = r.project_id
|
||||||
@@ -1575,11 +1527,10 @@ func (s *Store) GetRepoByProjectNameType(projectID string, name string, repoType
|
|||||||
WHERE r.project_id = (SELECT id FROM projects WHERE public_id = ?)
|
WHERE r.project_id = (SELECT id FROM projects WHERE public_id = ?)
|
||||||
AND r.name = ? AND r.type = ?`,
|
AND r.name = ? AND r.type = ?`,
|
||||||
projectID, name, repoType)
|
projectID, name, repoType)
|
||||||
err = row.Scan(&repo.ID, &repo.ProjectID, &repo.Name, &repo.Type, &repo.Path, &repo.CreatedBy, &created)
|
err = row.Scan(&repo.ID, &repo.ProjectID, &repo.Name, &repo.Type, &repo.Path, &repo.CreatedBy, &repo.CreatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return repo, err
|
return repo, err
|
||||||
}
|
}
|
||||||
repo.CreatedAt = created.Unix()
|
|
||||||
return repo, nil
|
return repo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1589,7 +1540,6 @@ func (s *Store) ListRepos(projectID string) ([]models.Repo, error) {
|
|||||||
var repos []models.Repo
|
var repos []models.Repo
|
||||||
var r models.Repo
|
var r models.Repo
|
||||||
var isForeign int
|
var isForeign int
|
||||||
var created time.Time
|
|
||||||
rows, err = s.Query(`
|
rows, err = s.Query(`
|
||||||
SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at, 0 AS is_foreign
|
SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at, 0 AS is_foreign
|
||||||
FROM repos r
|
FROM repos r
|
||||||
@@ -1611,11 +1561,10 @@ func (s *Store) ListRepos(projectID string) ([]models.Repo, error) {
|
|||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
err = rows.Scan(&r.ID, &r.ProjectID, &r.Name, &r.Type, &r.Path, &r.CreatedBy, &created, &isForeign)
|
err = rows.Scan(&r.ID, &r.ProjectID, &r.Name, &r.Type, &r.Path, &r.CreatedBy, &r.CreatedAt, &isForeign)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
r.CreatedAt = created.Unix()
|
|
||||||
r.IsForeign = isForeign != 0
|
r.IsForeign = isForeign != 0
|
||||||
repos = append(repos, r)
|
repos = append(repos, r)
|
||||||
}
|
}
|
||||||
@@ -1627,7 +1576,6 @@ func (s *Store) ListReposOwned(projectID string) ([]models.Repo, error) {
|
|||||||
var err error
|
var err error
|
||||||
var repos []models.Repo
|
var repos []models.Repo
|
||||||
var r models.Repo
|
var r models.Repo
|
||||||
var created time.Time
|
|
||||||
rows, err = s.Query(`
|
rows, err = s.Query(`
|
||||||
SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at
|
SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at
|
||||||
FROM repos r
|
FROM repos r
|
||||||
@@ -1641,11 +1589,10 @@ func (s *Store) ListReposOwned(projectID string) ([]models.Repo, error) {
|
|||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
err = rows.Scan(&r.ID, &r.ProjectID, &r.Name, &r.Type, &r.Path, &r.CreatedBy, &created)
|
err = rows.Scan(&r.ID, &r.ProjectID, &r.Name, &r.Type, &r.Path, &r.CreatedBy, &r.CreatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
r.CreatedAt = created.Unix()
|
|
||||||
repos = append(repos, r)
|
repos = append(repos, r)
|
||||||
}
|
}
|
||||||
return repos, rows.Err()
|
return repos, rows.Err()
|
||||||
@@ -1656,7 +1603,6 @@ func (s *Store) ListAllRepos() ([]models.Repo, error) {
|
|||||||
var err error
|
var err error
|
||||||
var repos []models.Repo
|
var repos []models.Repo
|
||||||
var r models.Repo
|
var r models.Repo
|
||||||
var created time.Time
|
|
||||||
rows, err = s.Query(`
|
rows, err = s.Query(`
|
||||||
SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at
|
SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at
|
||||||
FROM repos r
|
FROM repos r
|
||||||
@@ -1669,11 +1615,10 @@ func (s *Store) ListAllRepos() ([]models.Repo, error) {
|
|||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
err = rows.Scan(&r.ID, &r.ProjectID, &r.Name, &r.Type, &r.Path, &r.CreatedBy, &created)
|
err = rows.Scan(&r.ID, &r.ProjectID, &r.Name, &r.Type, &r.Path, &r.CreatedBy, &r.CreatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
r.CreatedAt = created.Unix()
|
|
||||||
repos = append(repos, r)
|
repos = append(repos, r)
|
||||||
}
|
}
|
||||||
return repos, rows.Err()
|
return repos, rows.Err()
|
||||||
@@ -1684,7 +1629,6 @@ func (s *Store) ListReposByProjectIDs(projectIDs []string) ([]models.Repo, error
|
|||||||
var err error
|
var err error
|
||||||
var repos []models.Repo
|
var repos []models.Repo
|
||||||
var r models.Repo
|
var r models.Repo
|
||||||
var created time.Time
|
|
||||||
var placeholders []string
|
var placeholders []string
|
||||||
var args []interface{}
|
var args []interface{}
|
||||||
var i int
|
var i int
|
||||||
@@ -1715,11 +1659,10 @@ func (s *Store) ListReposByProjectIDs(projectIDs []string) ([]models.Repo, error
|
|||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
err = rows.Scan(&r.ID, &r.ProjectID, &r.Name, &r.Type, &r.Path, &r.CreatedBy, &created)
|
err = rows.Scan(&r.ID, &r.ProjectID, &r.Name, &r.Type, &r.Path, &r.CreatedBy, &r.CreatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
r.CreatedAt = created.Unix()
|
|
||||||
repos = append(repos, r)
|
repos = append(repos, r)
|
||||||
}
|
}
|
||||||
return repos, rows.Err()
|
return repos, rows.Err()
|
||||||
@@ -1781,7 +1724,7 @@ func (s *Store) AttachRepoToProject(projectID string, repoID string) error {
|
|||||||
var err error
|
var err error
|
||||||
_, err = s.Exec(`INSERT INTO project_repos (project_id, repo_id, created_at)
|
_, err = s.Exec(`INSERT INTO project_repos (project_id, repo_id, created_at)
|
||||||
VALUES ((SELECT id FROM projects WHERE public_id = ?), (SELECT id FROM repos WHERE public_id = ?), ?)`,
|
VALUES ((SELECT id FROM projects WHERE public_id = ?), (SELECT id FROM repos WHERE public_id = ?), ?)`,
|
||||||
projectID, repoID, time.Now().UTC())
|
projectID, repoID, time.Now().UTC().Unix())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1825,7 +1768,6 @@ func (s *Store) ListAvailableReposForProject(projectID string, query string, lim
|
|||||||
var err error
|
var err error
|
||||||
var repos []models.Repo
|
var repos []models.Repo
|
||||||
var r models.Repo
|
var r models.Repo
|
||||||
var created time.Time
|
|
||||||
if limit <= 0 {
|
if limit <= 0 {
|
||||||
limit = 100
|
limit = 100
|
||||||
}
|
}
|
||||||
@@ -1871,11 +1813,10 @@ func (s *Store) ListAvailableReposForProject(projectID string, query string, lim
|
|||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
err = rows.Scan(&r.ID, &r.ProjectID, &r.Name, &r.Type, &r.Path, &r.CreatedBy, &created)
|
err = rows.Scan(&r.ID, &r.ProjectID, &r.Name, &r.Type, &r.Path, &r.CreatedBy, &r.CreatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
r.CreatedAt = created.Unix()
|
|
||||||
r.IsForeign = false
|
r.IsForeign = false
|
||||||
repos = append(repos, r)
|
repos = append(repos, r)
|
||||||
}
|
}
|
||||||
@@ -1885,7 +1826,6 @@ func (s *Store) ListAvailableReposForProject(projectID string, query string, lim
|
|||||||
func (s *Store) CreateIssue(issue models.Issue) (models.Issue, error) {
|
func (s *Store) CreateIssue(issue models.Issue) (models.Issue, error) {
|
||||||
var id string
|
var id string
|
||||||
var err error
|
var err error
|
||||||
var now time.Time
|
|
||||||
var nowUnix int64
|
var nowUnix int64
|
||||||
if issue.ID == "" {
|
if issue.ID == "" {
|
||||||
id, err = util.NewID()
|
id, err = util.NewID()
|
||||||
@@ -1894,8 +1834,7 @@ func (s *Store) CreateIssue(issue models.Issue) (models.Issue, error) {
|
|||||||
}
|
}
|
||||||
issue.ID = id
|
issue.ID = id
|
||||||
}
|
}
|
||||||
now = time.Now().UTC()
|
nowUnix = time.Now().UTC().Unix()
|
||||||
nowUnix = now.Unix()
|
|
||||||
issue.CreatedAt = nowUnix
|
issue.CreatedAt = nowUnix
|
||||||
issue.UpdatedAt = nowUnix
|
issue.UpdatedAt = nowUnix
|
||||||
if issue.Status == "" {
|
if issue.Status == "" {
|
||||||
@@ -1904,27 +1843,23 @@ func (s *Store) CreateIssue(issue models.Issue) (models.Issue, error) {
|
|||||||
_, err = s.Exec(`
|
_, err = s.Exec(`
|
||||||
INSERT INTO issues (public_id, project_id, title, body, status, created_by, assignee_id, created_at, updated_at)
|
INSERT INTO issues (public_id, project_id, title, body, status, created_by, assignee_id, created_at, updated_at)
|
||||||
VALUES (?, (SELECT id FROM projects WHERE public_id = ?), ?, ?, ?, (SELECT id FROM users WHERE public_id = ?), (SELECT id FROM users WHERE public_id = ?), ?, ?)
|
VALUES (?, (SELECT id FROM projects WHERE public_id = ?), ?, ?, ?, (SELECT id FROM users WHERE public_id = ?), (SELECT id FROM users WHERE public_id = ?), ?, ?)
|
||||||
`, issue.ID, issue.ProjectID, issue.Title, issue.Body, issue.Status, issue.CreatedBy, issue.AssigneeID, now, now)
|
`, issue.ID, issue.ProjectID, issue.Title, issue.Body, issue.Status, issue.CreatedBy, issue.AssigneeID, nowUnix, nowUnix)
|
||||||
return issue, err
|
return issue, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) UpdateIssue(issue models.Issue) error {
|
func (s *Store) UpdateIssue(issue models.Issue) error {
|
||||||
var err error
|
var err error
|
||||||
var now time.Time
|
|
||||||
var nowUnix int64
|
var nowUnix int64
|
||||||
now = time.Now().UTC()
|
nowUnix = time.Now().UTC().Unix()
|
||||||
nowUnix = now.Unix()
|
|
||||||
issue.UpdatedAt = nowUnix
|
issue.UpdatedAt = nowUnix
|
||||||
_, err = s.Exec(`UPDATE issues SET title = ?, body = ?, status = ?, assignee_id = (SELECT id FROM users WHERE public_id = ?), updated_at = ? WHERE public_id = ?`,
|
_, err = s.Exec(`UPDATE issues SET title = ?, body = ?, status = ?, assignee_id = (SELECT id FROM users WHERE public_id = ?), updated_at = ? WHERE public_id = ?`,
|
||||||
issue.Title, issue.Body, issue.Status, issue.AssigneeID, now, issue.ID)
|
issue.Title, issue.Body, issue.Status, issue.AssigneeID, nowUnix, issue.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) GetIssue(id string) (models.Issue, error) {
|
func (s *Store) GetIssue(id string) (models.Issue, error) {
|
||||||
var issue models.Issue
|
var issue models.Issue
|
||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var created time.Time
|
|
||||||
var updated time.Time
|
|
||||||
var err error
|
var err error
|
||||||
row = s.QueryRow(`SELECT i.public_id, p.public_id, i.title, i.body, i.status, cu.public_id, COALESCE(au.public_id, ''), i.created_at, i.updated_at
|
row = s.QueryRow(`SELECT i.public_id, p.public_id, i.title, i.body, i.status, cu.public_id, COALESCE(au.public_id, ''), i.created_at, i.updated_at
|
||||||
FROM issues i
|
FROM issues i
|
||||||
@@ -1932,12 +1867,10 @@ func (s *Store) GetIssue(id string) (models.Issue, error) {
|
|||||||
JOIN users cu ON cu.id = i.created_by
|
JOIN users cu ON cu.id = i.created_by
|
||||||
LEFT JOIN users au ON au.id = i.assignee_id
|
LEFT JOIN users au ON au.id = i.assignee_id
|
||||||
WHERE i.public_id = ?`, id)
|
WHERE i.public_id = ?`, id)
|
||||||
err = row.Scan(&issue.ID, &issue.ProjectID, &issue.Title, &issue.Body, &issue.Status, &issue.CreatedBy, &issue.AssigneeID, &created, &updated)
|
err = row.Scan(&issue.ID, &issue.ProjectID, &issue.Title, &issue.Body, &issue.Status, &issue.CreatedBy, &issue.AssigneeID, &issue.CreatedAt, &issue.UpdatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return issue, err
|
return issue, err
|
||||||
}
|
}
|
||||||
issue.CreatedAt = created.Unix()
|
|
||||||
issue.UpdatedAt = updated.Unix()
|
|
||||||
return issue, nil
|
return issue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1946,8 +1879,6 @@ func (s *Store) ListIssues(projectID string) ([]models.Issue, error) {
|
|||||||
var err error
|
var err error
|
||||||
var issues []models.Issue
|
var issues []models.Issue
|
||||||
var issue models.Issue
|
var issue models.Issue
|
||||||
var created time.Time
|
|
||||||
var updated time.Time
|
|
||||||
rows, err = s.Query(`SELECT i.public_id, p.public_id, i.title, i.body, i.status, cu.public_id, COALESCE(au.public_id, ''), i.created_at, i.updated_at
|
rows, err = s.Query(`SELECT i.public_id, p.public_id, i.title, i.body, i.status, cu.public_id, COALESCE(au.public_id, ''), i.created_at, i.updated_at
|
||||||
FROM issues i
|
FROM issues i
|
||||||
JOIN projects p ON p.id = i.project_id
|
JOIN projects p ON p.id = i.project_id
|
||||||
@@ -1960,12 +1891,10 @@ func (s *Store) ListIssues(projectID string) ([]models.Issue, error) {
|
|||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
err = rows.Scan(&issue.ID, &issue.ProjectID, &issue.Title, &issue.Body, &issue.Status, &issue.CreatedBy, &issue.AssigneeID, &created, &updated)
|
err = rows.Scan(&issue.ID, &issue.ProjectID, &issue.Title, &issue.Body, &issue.Status, &issue.CreatedBy, &issue.AssigneeID, &issue.CreatedAt, &issue.UpdatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
issue.CreatedAt = created.Unix()
|
|
||||||
issue.UpdatedAt = updated.Unix()
|
|
||||||
issues = append(issues, issue)
|
issues = append(issues, issue)
|
||||||
}
|
}
|
||||||
return issues, rows.Err()
|
return issues, rows.Err()
|
||||||
@@ -1974,7 +1903,6 @@ func (s *Store) ListIssues(projectID string) ([]models.Issue, error) {
|
|||||||
func (s *Store) AddIssueComment(comment models.IssueComment) (models.IssueComment, error) {
|
func (s *Store) AddIssueComment(comment models.IssueComment) (models.IssueComment, error) {
|
||||||
var id string
|
var id string
|
||||||
var err error
|
var err error
|
||||||
var now time.Time
|
|
||||||
var nowUnix int64
|
var nowUnix int64
|
||||||
if comment.ID == "" {
|
if comment.ID == "" {
|
||||||
id, err = util.NewID()
|
id, err = util.NewID()
|
||||||
@@ -1983,19 +1911,17 @@ func (s *Store) AddIssueComment(comment models.IssueComment) (models.IssueCommen
|
|||||||
}
|
}
|
||||||
comment.ID = id
|
comment.ID = id
|
||||||
}
|
}
|
||||||
now = time.Now().UTC()
|
nowUnix = time.Now().UTC().Unix()
|
||||||
nowUnix = now.Unix()
|
|
||||||
comment.CreatedAt = nowUnix
|
comment.CreatedAt = nowUnix
|
||||||
_, err = s.Exec(`INSERT INTO issue_comments (public_id, issue_id, body, created_by, created_at)
|
_, err = s.Exec(`INSERT INTO issue_comments (public_id, issue_id, body, created_by, created_at)
|
||||||
VALUES (?, (SELECT id FROM issues WHERE public_id = ?), ?, (SELECT id FROM users WHERE public_id = ?), ?)`,
|
VALUES (?, (SELECT id FROM issues WHERE public_id = ?), ?, (SELECT id FROM users WHERE public_id = ?), ?)`,
|
||||||
comment.ID, comment.IssueID, comment.Body, comment.CreatedBy, now)
|
comment.ID, comment.IssueID, comment.Body, comment.CreatedBy, nowUnix)
|
||||||
return comment, err
|
return comment, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) CreateWikiPage(page models.WikiPage) (models.WikiPage, error) {
|
func (s *Store) CreateWikiPage(page models.WikiPage) (models.WikiPage, error) {
|
||||||
var id string
|
var id string
|
||||||
var err error
|
var err error
|
||||||
var now time.Time
|
|
||||||
var nowUnix int64
|
var nowUnix int64
|
||||||
if page.ID == "" {
|
if page.ID == "" {
|
||||||
id, err = util.NewID()
|
id, err = util.NewID()
|
||||||
@@ -2004,23 +1930,20 @@ func (s *Store) CreateWikiPage(page models.WikiPage) (models.WikiPage, error) {
|
|||||||
}
|
}
|
||||||
page.ID = id
|
page.ID = id
|
||||||
}
|
}
|
||||||
now = time.Now().UTC()
|
nowUnix = time.Now().UTC().Unix()
|
||||||
nowUnix = now.Unix()
|
|
||||||
page.UpdatedAt = nowUnix
|
page.UpdatedAt = nowUnix
|
||||||
_, err = s.Exec(`INSERT INTO wiki_pages (public_id, project_id, title, slug, body, created_by, updated_at)
|
_, err = s.Exec(`INSERT INTO wiki_pages (public_id, project_id, title, slug, body, created_by, updated_at)
|
||||||
VALUES (?, (SELECT id FROM projects WHERE public_id = ?), ?, ?, ?, (SELECT id FROM users WHERE public_id = ?), ?)`,
|
VALUES (?, (SELECT id FROM projects WHERE public_id = ?), ?, ?, ?, (SELECT id FROM users WHERE public_id = ?), ?)`,
|
||||||
page.ID, page.ProjectID, page.Title, page.Slug, page.Body, page.CreatedBy, now)
|
page.ID, page.ProjectID, page.Title, page.Slug, page.Body, page.CreatedBy, nowUnix)
|
||||||
return page, err
|
return page, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) UpdateWikiPage(page models.WikiPage) error {
|
func (s *Store) UpdateWikiPage(page models.WikiPage) error {
|
||||||
var err error
|
var err error
|
||||||
var now time.Time
|
|
||||||
var nowUnix int64
|
var nowUnix int64
|
||||||
now = time.Now().UTC()
|
nowUnix = time.Now().UTC().Unix()
|
||||||
nowUnix = now.Unix()
|
|
||||||
page.UpdatedAt = nowUnix
|
page.UpdatedAt = nowUnix
|
||||||
_, err = s.Exec(`UPDATE wiki_pages SET title = ?, body = ?, updated_at = ? WHERE public_id = ?`, page.Title, page.Body, now, page.ID)
|
_, err = s.Exec(`UPDATE wiki_pages SET title = ?, body = ?, updated_at = ? WHERE public_id = ?`, page.Title, page.Body, nowUnix, page.ID)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2029,7 +1952,6 @@ func (s *Store) ListWikiPages(projectID string) ([]models.WikiPage, error) {
|
|||||||
var err error
|
var err error
|
||||||
var pages []models.WikiPage
|
var pages []models.WikiPage
|
||||||
var page models.WikiPage
|
var page models.WikiPage
|
||||||
var updated time.Time
|
|
||||||
rows, err = s.Query(`SELECT w.public_id, p.public_id, w.title, w.slug, w.body, u.public_id, w.updated_at
|
rows, err = s.Query(`SELECT w.public_id, p.public_id, w.title, w.slug, w.body, u.public_id, w.updated_at
|
||||||
FROM wiki_pages w
|
FROM wiki_pages w
|
||||||
JOIN projects p ON p.id = w.project_id
|
JOIN projects p ON p.id = w.project_id
|
||||||
@@ -2041,11 +1963,10 @@ func (s *Store) ListWikiPages(projectID string) ([]models.WikiPage, error) {
|
|||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
err = rows.Scan(&page.ID, &page.ProjectID, &page.Title, &page.Slug, &page.Body, &page.CreatedBy, &updated)
|
err = rows.Scan(&page.ID, &page.ProjectID, &page.Title, &page.Slug, &page.Body, &page.CreatedBy, &page.UpdatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
page.UpdatedAt = updated.Unix()
|
|
||||||
pages = append(pages, page)
|
pages = append(pages, page)
|
||||||
}
|
}
|
||||||
return pages, rows.Err()
|
return pages, rows.Err()
|
||||||
@@ -2054,25 +1975,22 @@ func (s *Store) ListWikiPages(projectID string) ([]models.WikiPage, error) {
|
|||||||
func (s *Store) GetWikiPage(id string) (models.WikiPage, error) {
|
func (s *Store) GetWikiPage(id string) (models.WikiPage, error) {
|
||||||
var page models.WikiPage
|
var page models.WikiPage
|
||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var updated time.Time
|
|
||||||
var err error
|
var err error
|
||||||
row = s.QueryRow(`SELECT w.public_id, p.public_id, w.title, w.slug, w.body, u.public_id, w.updated_at
|
row = s.QueryRow(`SELECT w.public_id, p.public_id, w.title, w.slug, w.body, u.public_id, w.updated_at
|
||||||
FROM wiki_pages w
|
FROM wiki_pages w
|
||||||
JOIN projects p ON p.id = w.project_id
|
JOIN projects p ON p.id = w.project_id
|
||||||
JOIN users u ON u.id = w.created_by
|
JOIN users u ON u.id = w.created_by
|
||||||
WHERE w.public_id = ?`, id)
|
WHERE w.public_id = ?`, id)
|
||||||
err = row.Scan(&page.ID, &page.ProjectID, &page.Title, &page.Slug, &page.Body, &page.CreatedBy, &updated)
|
err = row.Scan(&page.ID, &page.ProjectID, &page.Title, &page.Slug, &page.Body, &page.CreatedBy, &page.UpdatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return page, err
|
return page, err
|
||||||
}
|
}
|
||||||
page.UpdatedAt = updated.Unix()
|
|
||||||
return page, nil
|
return page, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) CreateUpload(upload models.Upload) (models.Upload, error) {
|
func (s *Store) CreateUpload(upload models.Upload) (models.Upload, error) {
|
||||||
var id string
|
var id string
|
||||||
var err error
|
var err error
|
||||||
var now time.Time
|
|
||||||
var nowUnix int64
|
var nowUnix int64
|
||||||
if upload.ID == "" {
|
if upload.ID == "" {
|
||||||
id, err = util.NewID()
|
id, err = util.NewID()
|
||||||
@@ -2081,30 +1999,27 @@ func (s *Store) CreateUpload(upload models.Upload) (models.Upload, error) {
|
|||||||
}
|
}
|
||||||
upload.ID = id
|
upload.ID = id
|
||||||
}
|
}
|
||||||
now = time.Now().UTC()
|
nowUnix = time.Now().UTC().Unix()
|
||||||
nowUnix = now.Unix()
|
|
||||||
upload.CreatedAt = nowUnix
|
upload.CreatedAt = nowUnix
|
||||||
_, err = s.Exec(`INSERT INTO uploads (public_id, project_id, filename, content_type, size, storage_path, created_by, created_at)
|
_, err = s.Exec(`INSERT INTO uploads (public_id, project_id, filename, content_type, size, storage_path, created_by, created_at)
|
||||||
VALUES (?, (SELECT id FROM projects WHERE public_id = ?), ?, ?, ?, ?, (SELECT id FROM users WHERE public_id = ?), ?)`,
|
VALUES (?, (SELECT id FROM projects WHERE public_id = ?), ?, ?, ?, ?, (SELECT id FROM users WHERE public_id = ?), ?)`,
|
||||||
upload.ID, upload.ProjectID, upload.Filename, upload.ContentType, upload.Size, upload.StoragePath, upload.CreatedBy, now)
|
upload.ID, upload.ProjectID, upload.Filename, upload.ContentType, upload.Size, upload.StoragePath, upload.CreatedBy, nowUnix)
|
||||||
return upload, err
|
return upload, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) GetUpload(id string) (models.Upload, error) {
|
func (s *Store) GetUpload(id string) (models.Upload, error) {
|
||||||
var upload models.Upload
|
var upload models.Upload
|
||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var created time.Time
|
|
||||||
var err error
|
var err error
|
||||||
row = s.QueryRow(`SELECT up.public_id, p.public_id, up.filename, up.content_type, up.size, up.storage_path, u.public_id, up.created_at
|
row = s.QueryRow(`SELECT up.public_id, p.public_id, up.filename, up.content_type, up.size, up.storage_path, u.public_id, up.created_at
|
||||||
FROM uploads up
|
FROM uploads up
|
||||||
JOIN projects p ON p.id = up.project_id
|
JOIN projects p ON p.id = up.project_id
|
||||||
JOIN users u ON u.id = up.created_by
|
JOIN users u ON u.id = up.created_by
|
||||||
WHERE up.public_id = ?`, id)
|
WHERE up.public_id = ?`, id)
|
||||||
err = row.Scan(&upload.ID, &upload.ProjectID, &upload.Filename, &upload.ContentType, &upload.Size, &upload.StoragePath, &upload.CreatedBy, &created)
|
err = row.Scan(&upload.ID, &upload.ProjectID, &upload.Filename, &upload.ContentType, &upload.Size, &upload.StoragePath, &upload.CreatedBy, &upload.CreatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return upload, err
|
return upload, err
|
||||||
}
|
}
|
||||||
upload.CreatedAt = created.Unix()
|
|
||||||
return upload, nil
|
return upload, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2113,7 +2028,6 @@ func (s *Store) ListUploads(projectID string) ([]models.Upload, error) {
|
|||||||
var err error
|
var err error
|
||||||
var uploads []models.Upload
|
var uploads []models.Upload
|
||||||
var upload models.Upload
|
var upload models.Upload
|
||||||
var created time.Time
|
|
||||||
rows, err = s.Query(`SELECT up.public_id, p.public_id, up.filename, up.content_type, up.size, up.storage_path, u.public_id, up.created_at
|
rows, err = s.Query(`SELECT up.public_id, p.public_id, up.filename, up.content_type, up.size, up.storage_path, u.public_id, up.created_at
|
||||||
FROM uploads up
|
FROM uploads up
|
||||||
JOIN projects p ON p.id = up.project_id
|
JOIN projects p ON p.id = up.project_id
|
||||||
@@ -2125,11 +2039,10 @@ func (s *Store) ListUploads(projectID string) ([]models.Upload, error) {
|
|||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
err = rows.Scan(&upload.ID, &upload.ProjectID, &upload.Filename, &upload.ContentType, &upload.Size, &upload.StoragePath, &upload.CreatedBy, &created)
|
err = rows.Scan(&upload.ID, &upload.ProjectID, &upload.Filename, &upload.ContentType, &upload.Size, &upload.StoragePath, &upload.CreatedBy, &upload.CreatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
upload.CreatedAt = created.Unix()
|
|
||||||
uploads = append(uploads, upload)
|
uploads = append(uploads, upload)
|
||||||
}
|
}
|
||||||
return uploads, rows.Err()
|
return uploads, rows.Err()
|
||||||
|
|||||||
@@ -14,20 +14,16 @@ type UserTOTP struct {
|
|||||||
func (s *Store) GetUserTOTP(userID string) (UserTOTP, error) {
|
func (s *Store) GetUserTOTP(userID string) (UserTOTP, error) {
|
||||||
var item UserTOTP
|
var item UserTOTP
|
||||||
var row *sql.Row
|
var row *sql.Row
|
||||||
var created time.Time
|
|
||||||
var updated time.Time
|
|
||||||
var err error
|
var err error
|
||||||
row = s.QueryRow(`
|
row = s.QueryRow(`
|
||||||
SELECT COALESCE(t.secret_encrypted, ''), COALESCE(t.pending_secret_encrypted, ''), COALESCE(t.enabled, 0), t.created_at, t.updated_at
|
SELECT COALESCE(t.secret_encrypted, ''), COALESCE(t.pending_secret_encrypted, ''), COALESCE(t.enabled, 0), t.created_at, t.updated_at
|
||||||
FROM user_totp t JOIN users u ON u.id = t.user_id
|
FROM user_totp t JOIN users u ON u.id = t.user_id
|
||||||
WHERE u.public_id = ?
|
WHERE u.public_id = ?
|
||||||
`, userID)
|
`, userID)
|
||||||
err = row.Scan(&item.SecretEncrypted, &item.PendingSecretEncrypted, &item.Enabled, &created, &updated)
|
err = row.Scan(&item.SecretEncrypted, &item.PendingSecretEncrypted, &item.Enabled, &item.CreatedAt, &item.UpdatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return item, err
|
return item, err
|
||||||
}
|
}
|
||||||
item.CreatedAt = created.Unix()
|
|
||||||
item.UpdatedAt = updated.Unix()
|
|
||||||
return item, nil
|
return item, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,25 +48,25 @@ func (s *Store) UserRequiresTOTP(userID string) (bool, error) {
|
|||||||
|
|
||||||
func (s *Store) UpsertUserTOTPPending(userID string, pendingSecretEncrypted string) error {
|
func (s *Store) UpsertUserTOTPPending(userID string, pendingSecretEncrypted string) error {
|
||||||
var err error
|
var err error
|
||||||
var now time.Time
|
var nowUnix int64
|
||||||
now = time.Now().UTC()
|
nowUnix = time.Now().UTC().Unix()
|
||||||
_, err = s.Exec(`
|
_, err = s.Exec(`
|
||||||
INSERT INTO user_totp (user_id, secret_encrypted, pending_secret_encrypted, enabled, created_at, updated_at)
|
INSERT INTO user_totp (user_id, secret_encrypted, pending_secret_encrypted, enabled, created_at, updated_at)
|
||||||
VALUES ((SELECT id FROM users WHERE public_id = ?), '', ?, 0, ?, ?)
|
VALUES ((SELECT id FROM users WHERE public_id = ?), '', ?, 0, ?, ?)
|
||||||
ON CONFLICT(user_id) DO UPDATE SET pending_secret_encrypted = excluded.pending_secret_encrypted, updated_at = excluded.updated_at
|
ON CONFLICT(user_id) DO UPDATE SET pending_secret_encrypted = excluded.pending_secret_encrypted, updated_at = excluded.updated_at
|
||||||
`, userID, pendingSecretEncrypted, now, now)
|
`, userID, pendingSecretEncrypted, nowUnix, nowUnix)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) EnableUserTOTP(userID string, secretEncrypted string) error {
|
func (s *Store) EnableUserTOTP(userID string, secretEncrypted string) error {
|
||||||
var err error
|
var err error
|
||||||
var now time.Time
|
var nowUnix int64
|
||||||
now = time.Now().UTC()
|
nowUnix = time.Now().UTC().Unix()
|
||||||
_, err = s.Exec(`
|
_, err = s.Exec(`
|
||||||
INSERT INTO user_totp (user_id, secret_encrypted, pending_secret_encrypted, enabled, created_at, updated_at)
|
INSERT INTO user_totp (user_id, secret_encrypted, pending_secret_encrypted, enabled, created_at, updated_at)
|
||||||
VALUES ((SELECT id FROM users WHERE public_id = ?), ?, '', 1, ?, ?)
|
VALUES ((SELECT id FROM users WHERE public_id = ?), ?, '', 1, ?, ?)
|
||||||
ON CONFLICT(user_id) DO UPDATE SET secret_encrypted = excluded.secret_encrypted, pending_secret_encrypted = '', enabled = 1, updated_at = excluded.updated_at
|
ON CONFLICT(user_id) DO UPDATE SET secret_encrypted = excluded.secret_encrypted, pending_secret_encrypted = '', enabled = 1, updated_at = excluded.updated_at
|
||||||
`, userID, secretEncrypted, now, now)
|
`, userID, secretEncrypted, nowUnix, nowUnix)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1815,7 +1815,7 @@ func (api *API) UpdateProject(w http.ResponseWriter, r *http.Request, params map
|
|||||||
project.HomePage = normalizeProjectHomePage(req.HomePage)
|
project.HomePage = normalizeProjectHomePage(req.HomePage)
|
||||||
}
|
}
|
||||||
if project.HomePage == "" {
|
if project.HomePage == "" {
|
||||||
project.HomePage = "info"
|
project.HomePage = "settings"
|
||||||
}
|
}
|
||||||
user, _ = middleware.UserFromContext(r.Context())
|
user, _ = middleware.UserFromContext(r.Context())
|
||||||
project.UpdatedBy = user.ID
|
project.UpdatedBy = user.ID
|
||||||
@@ -5448,10 +5448,13 @@ func normalizeRole(role string) string {
|
|||||||
func normalizeProjectHomePage(value string) string {
|
func normalizeProjectHomePage(value string) string {
|
||||||
var v string
|
var v string
|
||||||
v = strings.ToLower(strings.TrimSpace(value))
|
v = strings.ToLower(strings.TrimSpace(value))
|
||||||
if v == "repos" || v == "issues" || v == "wiki" || v == "files" || v == "info" {
|
if v == "info" {
|
||||||
|
return "settings"
|
||||||
|
}
|
||||||
|
if v == "repos" || v == "issues" || v == "wiki" || v == "files" || v == "settings" {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
return "info"
|
return "settings"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1762,6 +1762,10 @@ func (api *API) CreateSSHSessionForSelf(w http.ResponseWriter, r *http.Request,
|
|||||||
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "server_id does not match access profile")
|
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "server_id does not match access profile")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if !profile.Server.Enabled {
|
||||||
|
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "ssh server is disabled")
|
||||||
|
return
|
||||||
|
}
|
||||||
item = models.SSHSession{
|
item = models.SSHSession{
|
||||||
ProfileID: profile.ID,
|
ProfileID: profile.ID,
|
||||||
ServerID: profile.ServerID,
|
ServerID: profile.ServerID,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ func TestUserJSONTags(t *testing.T) {
|
|||||||
Email: "a@x",
|
Email: "a@x",
|
||||||
IsAdmin: true,
|
IsAdmin: true,
|
||||||
Disabled: true,
|
Disabled: true,
|
||||||
AuthSource: "db",
|
AuthProviderID: "p1",
|
||||||
CreatedAt: 1,
|
CreatedAt: 1,
|
||||||
UpdatedAt: 2,
|
UpdatedAt: 2,
|
||||||
}
|
}
|
||||||
@@ -37,6 +37,9 @@ func TestUserJSONTags(t *testing.T) {
|
|||||||
if _, ok := decoded["disabled"]; !ok {
|
if _, ok := decoded["disabled"]; !ok {
|
||||||
t.Fatalf("missing disabled json key")
|
t.Fatalf("missing disabled json key")
|
||||||
}
|
}
|
||||||
|
if _, ok := decoded["auth_provider_id"]; !ok {
|
||||||
|
t.Fatalf("missing auth_provider_id json key")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAPIKeyJSONTags(t *testing.T) {
|
func TestAPIKeyJSONTags(t *testing.T) {
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ CREATE TABLE IF NOT EXISTS projects (
|
|||||||
slug TEXT NOT NULL UNIQUE,
|
slug TEXT NOT NULL UNIQUE,
|
||||||
name TEXT NOT NULL,
|
name TEXT NOT NULL,
|
||||||
description TEXT NOT NULL,
|
description TEXT NOT NULL,
|
||||||
home_page TEXT NOT NULL DEFAULT 'info',
|
home_page TEXT NOT NULL DEFAULT 'settings',
|
||||||
created_by INTEGER NOT NULL,
|
created_by INTEGER NOT NULL,
|
||||||
updated_by INTEGER NOT NULL DEFAULT 0,
|
updated_by INTEGER NOT NULL DEFAULT 0,
|
||||||
created_at TIMESTAMP NOT NULL,
|
created_at TIMESTAMP NOT NULL,
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
-- users: created_at, updated_at
|
||||||
|
ALTER TABLE users ADD COLUMN created_at_new INTEGER NOT NULL DEFAULT 0;
|
||||||
|
ALTER TABLE users ADD COLUMN updated_at_new INTEGER NOT NULL DEFAULT 0;
|
||||||
|
UPDATE users SET
|
||||||
|
created_at_new = CASE WHEN typeof(created_at) = 'integer' THEN created_at ELSE COALESCE(CAST(strftime('%s', substr(created_at, 1, 19)) AS INTEGER), 0) END,
|
||||||
|
updated_at_new = CASE WHEN typeof(updated_at) = 'integer' THEN updated_at ELSE COALESCE(CAST(strftime('%s', substr(updated_at, 1, 19)) AS INTEGER), 0) END;
|
||||||
|
ALTER TABLE users DROP COLUMN created_at;
|
||||||
|
ALTER TABLE users DROP COLUMN updated_at;
|
||||||
|
ALTER TABLE users RENAME COLUMN created_at_new TO created_at;
|
||||||
|
ALTER TABLE users RENAME COLUMN updated_at_new TO updated_at;
|
||||||
|
|
||||||
|
-- sessions: expires_at, created_at
|
||||||
|
ALTER TABLE sessions ADD COLUMN expires_at_new INTEGER NOT NULL DEFAULT 0;
|
||||||
|
ALTER TABLE sessions ADD COLUMN created_at_new INTEGER NOT NULL DEFAULT 0;
|
||||||
|
UPDATE sessions SET
|
||||||
|
expires_at_new = CASE WHEN typeof(expires_at) = 'integer' THEN expires_at ELSE COALESCE(CAST(strftime('%s', substr(expires_at, 1, 19)) AS INTEGER), 0) END,
|
||||||
|
created_at_new = CASE WHEN typeof(created_at) = 'integer' THEN created_at ELSE COALESCE(CAST(strftime('%s', substr(created_at, 1, 19)) AS INTEGER), 0) END;
|
||||||
|
ALTER TABLE sessions DROP COLUMN expires_at;
|
||||||
|
ALTER TABLE sessions DROP COLUMN created_at;
|
||||||
|
ALTER TABLE sessions RENAME COLUMN expires_at_new TO expires_at;
|
||||||
|
ALTER TABLE sessions RENAME COLUMN created_at_new TO created_at;
|
||||||
|
|
||||||
|
-- user_totp: created_at, updated_at
|
||||||
|
ALTER TABLE user_totp ADD COLUMN created_at_new INTEGER NOT NULL DEFAULT 0;
|
||||||
|
ALTER TABLE user_totp ADD COLUMN updated_at_new INTEGER NOT NULL DEFAULT 0;
|
||||||
|
UPDATE user_totp SET
|
||||||
|
created_at_new = CASE WHEN typeof(created_at) = 'integer' THEN created_at ELSE COALESCE(CAST(strftime('%s', substr(created_at, 1, 19)) AS INTEGER), 0) END,
|
||||||
|
updated_at_new = CASE WHEN typeof(updated_at) = 'integer' THEN updated_at ELSE COALESCE(CAST(strftime('%s', substr(updated_at, 1, 19)) AS INTEGER), 0) END;
|
||||||
|
ALTER TABLE user_totp DROP COLUMN created_at;
|
||||||
|
ALTER TABLE user_totp DROP COLUMN updated_at;
|
||||||
|
ALTER TABLE user_totp RENAME COLUMN created_at_new TO created_at;
|
||||||
|
ALTER TABLE user_totp RENAME COLUMN updated_at_new TO updated_at;
|
||||||
|
|
||||||
|
-- projects: special case - use created_at_unix/updated_at_unix as source of truth
|
||||||
|
ALTER TABLE projects ADD COLUMN created_at_new INTEGER NOT NULL DEFAULT 0;
|
||||||
|
ALTER TABLE projects ADD COLUMN updated_at_new INTEGER NOT NULL DEFAULT 0;
|
||||||
|
UPDATE projects SET
|
||||||
|
created_at_new = CASE WHEN created_at_unix != 0 THEN created_at_unix
|
||||||
|
WHEN typeof(created_at) = 'integer' THEN created_at
|
||||||
|
ELSE COALESCE(CAST(strftime('%s', substr(created_at, 1, 19)) AS INTEGER), 0) END,
|
||||||
|
updated_at_new = CASE WHEN updated_at_unix != 0 THEN updated_at_unix
|
||||||
|
WHEN typeof(updated_at) = 'integer' THEN updated_at
|
||||||
|
ELSE COALESCE(CAST(strftime('%s', substr(updated_at, 1, 19)) AS INTEGER), 0) END;
|
||||||
|
ALTER TABLE projects DROP COLUMN created_at;
|
||||||
|
ALTER TABLE projects DROP COLUMN updated_at;
|
||||||
|
ALTER TABLE projects DROP COLUMN created_at_unix;
|
||||||
|
ALTER TABLE projects DROP COLUMN updated_at_unix;
|
||||||
|
ALTER TABLE projects RENAME COLUMN created_at_new TO created_at;
|
||||||
|
ALTER TABLE projects RENAME COLUMN updated_at_new TO updated_at;
|
||||||
|
|
||||||
|
-- project_members: created_at
|
||||||
|
ALTER TABLE project_members ADD COLUMN created_at_new INTEGER NOT NULL DEFAULT 0;
|
||||||
|
UPDATE project_members SET
|
||||||
|
created_at_new = CASE WHEN typeof(created_at) = 'integer' THEN created_at ELSE COALESCE(CAST(strftime('%s', substr(created_at, 1, 19)) AS INTEGER), 0) END;
|
||||||
|
ALTER TABLE project_members DROP COLUMN created_at;
|
||||||
|
ALTER TABLE project_members RENAME COLUMN created_at_new TO created_at;
|
||||||
|
|
||||||
|
-- repos: created_at
|
||||||
|
ALTER TABLE repos ADD COLUMN created_at_new INTEGER NOT NULL DEFAULT 0;
|
||||||
|
UPDATE repos SET
|
||||||
|
created_at_new = CASE WHEN typeof(created_at) = 'integer' THEN created_at ELSE COALESCE(CAST(strftime('%s', substr(created_at, 1, 19)) AS INTEGER), 0) END;
|
||||||
|
ALTER TABLE repos DROP COLUMN created_at;
|
||||||
|
ALTER TABLE repos RENAME COLUMN created_at_new TO created_at;
|
||||||
|
|
||||||
|
-- issues: created_at, updated_at
|
||||||
|
ALTER TABLE issues ADD COLUMN created_at_new INTEGER NOT NULL DEFAULT 0;
|
||||||
|
ALTER TABLE issues ADD COLUMN updated_at_new INTEGER NOT NULL DEFAULT 0;
|
||||||
|
UPDATE issues SET
|
||||||
|
created_at_new = CASE WHEN typeof(created_at) = 'integer' THEN created_at ELSE COALESCE(CAST(strftime('%s', substr(created_at, 1, 19)) AS INTEGER), 0) END,
|
||||||
|
updated_at_new = CASE WHEN typeof(updated_at) = 'integer' THEN updated_at ELSE COALESCE(CAST(strftime('%s', substr(updated_at, 1, 19)) AS INTEGER), 0) END;
|
||||||
|
ALTER TABLE issues DROP COLUMN created_at;
|
||||||
|
ALTER TABLE issues DROP COLUMN updated_at;
|
||||||
|
ALTER TABLE issues RENAME COLUMN created_at_new TO created_at;
|
||||||
|
ALTER TABLE issues RENAME COLUMN updated_at_new TO updated_at;
|
||||||
|
|
||||||
|
-- issue_comments: created_at
|
||||||
|
ALTER TABLE issue_comments ADD COLUMN created_at_new INTEGER NOT NULL DEFAULT 0;
|
||||||
|
UPDATE issue_comments SET
|
||||||
|
created_at_new = CASE WHEN typeof(created_at) = 'integer' THEN created_at ELSE COALESCE(CAST(strftime('%s', substr(created_at, 1, 19)) AS INTEGER), 0) END;
|
||||||
|
ALTER TABLE issue_comments DROP COLUMN created_at;
|
||||||
|
ALTER TABLE issue_comments RENAME COLUMN created_at_new TO created_at;
|
||||||
|
|
||||||
|
-- wiki_pages: updated_at
|
||||||
|
ALTER TABLE wiki_pages ADD COLUMN updated_at_new INTEGER NOT NULL DEFAULT 0;
|
||||||
|
UPDATE wiki_pages SET
|
||||||
|
updated_at_new = CASE WHEN typeof(updated_at) = 'integer' THEN updated_at ELSE COALESCE(CAST(strftime('%s', substr(updated_at, 1, 19)) AS INTEGER), 0) END;
|
||||||
|
ALTER TABLE wiki_pages DROP COLUMN updated_at;
|
||||||
|
ALTER TABLE wiki_pages RENAME COLUMN updated_at_new TO updated_at;
|
||||||
|
|
||||||
|
-- uploads: created_at
|
||||||
|
ALTER TABLE uploads ADD COLUMN created_at_new INTEGER NOT NULL DEFAULT 0;
|
||||||
|
UPDATE uploads SET
|
||||||
|
created_at_new = CASE WHEN typeof(created_at) = 'integer' THEN created_at ELSE COALESCE(CAST(strftime('%s', substr(created_at, 1, 19)) AS INTEGER), 0) END;
|
||||||
|
ALTER TABLE uploads DROP COLUMN created_at;
|
||||||
|
ALTER TABLE uploads RENAME COLUMN created_at_new TO created_at;
|
||||||
|
|
||||||
|
-- project_repos: created_at
|
||||||
|
ALTER TABLE project_repos ADD COLUMN created_at_new INTEGER NOT NULL DEFAULT 0;
|
||||||
|
UPDATE project_repos SET
|
||||||
|
created_at_new = CASE WHEN typeof(created_at) = 'integer' THEN created_at ELSE COALESCE(CAST(strftime('%s', substr(created_at, 1, 19)) AS INTEGER), 0) END;
|
||||||
|
ALTER TABLE project_repos DROP COLUMN created_at;
|
||||||
|
ALTER TABLE project_repos RENAME COLUMN created_at_new TO created_at;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
@@ -44,7 +44,7 @@ func createTestUser(t *testing.T, store *db.Store, username string) models.User
|
|||||||
Email: username + "@local",
|
Email: username + "@local",
|
||||||
IsAdmin: false,
|
IsAdmin: false,
|
||||||
Disabled: false,
|
Disabled: false,
|
||||||
AuthSource: "db",
|
AuthProviderID: "",
|
||||||
}
|
}
|
||||||
user, err = store.CreateUser(user, passwordHash)
|
user, err = store.CreateUser(user, passwordHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
+1
-1
@@ -97,7 +97,7 @@ export interface Project {
|
|||||||
slug: string
|
slug: string
|
||||||
name: string
|
name: string
|
||||||
description: string
|
description: string
|
||||||
home_page?: 'info' | 'repos' | 'issues' | 'wiki' | 'files'
|
home_page?: 'settings' | 'repos' | 'issues' | 'wiki' | 'files'
|
||||||
created_by?: string
|
created_by?: string
|
||||||
updated_by?: string
|
updated_by?: string
|
||||||
created_by_name?: string
|
created_by_name?: string
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import LoginPage from '../pages/LoginPage'
|
|||||||
import ProjectsPage from '../pages/ProjectsPage'
|
import ProjectsPage from '../pages/ProjectsPage'
|
||||||
import GlobalReposPage from '../pages/GlobalReposPage'
|
import GlobalReposPage from '../pages/GlobalReposPage'
|
||||||
import ProjectEntryPage from '../pages/ProjectEntryPage'
|
import ProjectEntryPage from '../pages/ProjectEntryPage'
|
||||||
import ProjectHomePage from '../pages/ProjectHomePage'
|
import ProjectSettingsPage from '../pages/ProjectSettingsPage'
|
||||||
import ReposPage from '../pages/ReposPage'
|
import ReposPage from '../pages/ReposPage'
|
||||||
import AdminUsersPage from '../pages/AdminUsersPage'
|
import AdminUsersPage from '../pages/AdminUsersPage'
|
||||||
import AdminUserGroupsPage from '../pages/AdminUserGroupsPage'
|
import AdminUserGroupsPage from '../pages/AdminUserGroupsPage'
|
||||||
@@ -87,7 +87,7 @@ export const routes: RouteObject[] = [
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
{ path: 'projects/:projectId', element: <ProjectEntryPage /> },
|
{ path: 'projects/:projectId', element: <ProjectEntryPage /> },
|
||||||
{ path: 'projects/:projectId/info', element: <ProjectHomePage /> },
|
{ path: 'projects/:projectId/settings', element: <ProjectSettingsPage /> },
|
||||||
{ path: 'projects/:projectId/repos', element: <ReposPage /> },
|
{ path: 'projects/:projectId/repos', element: <ReposPage /> },
|
||||||
{ path: 'projects/:projectId/repos/:repoId', element: withRouteSuspense(<RepoDetailPage />) },
|
{ path: 'projects/:projectId/repos/:repoId', element: withRouteSuspense(<RepoDetailPage />) },
|
||||||
{ path: 'projects/:projectId/repos/:repoId/branches', element: withRouteSuspense(<BranchesPage />) },
|
{ path: 'projects/:projectId/repos/:repoId/branches', element: withRouteSuspense(<BranchesPage />) },
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import remarkGfm from 'remark-gfm'
|
|||||||
import FormDialogContent from './FormDialogContent'
|
import FormDialogContent from './FormDialogContent'
|
||||||
import SelectField from './SelectField'
|
import SelectField from './SelectField'
|
||||||
|
|
||||||
export type ProjectHomePageValue = 'info' | 'repos' | 'issues' | 'wiki' | 'files'
|
export type ProjectHomePageValue = 'settings' | 'repos' | 'issues' | 'wiki' | 'files'
|
||||||
export type ProjectDescriptionTab = 'write' | 'preview'
|
export type ProjectDescriptionTab = 'write' | 'preview'
|
||||||
|
|
||||||
type ProjectFormDialogProps = {
|
type ProjectFormDialogProps = {
|
||||||
@@ -76,7 +76,7 @@ export default function ProjectFormDialog(props: ProjectFormDialogProps) {
|
|||||||
<MenuItem value="issues">Issues</MenuItem>
|
<MenuItem value="issues">Issues</MenuItem>
|
||||||
<MenuItem value="wiki">Wiki</MenuItem>
|
<MenuItem value="wiki">Wiki</MenuItem>
|
||||||
<MenuItem value="files">Files</MenuItem>
|
<MenuItem value="files">Files</MenuItem>
|
||||||
<MenuItem value="info">Settings</MenuItem>
|
<MenuItem value="settings">Settings</MenuItem>
|
||||||
</SelectField>
|
</SelectField>
|
||||||
<Box sx={{ mt: 1 }}>
|
<Box sx={{ mt: 1 }}>
|
||||||
<Tabs
|
<Tabs
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ export default function ProjectNavBar(props: ProjectNavBarProps) {
|
|||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
component={Link}
|
component={Link}
|
||||||
to={`/projects/${projectId}/info`}
|
to={`/projects/${projectId}/settings`}
|
||||||
startIcon={<InfoOutlinedIcon />}
|
startIcon={<InfoOutlinedIcon />}
|
||||||
sx={{ justifyContent: 'flex-start', minWidth: 0, width: 'fit-content' }}
|
sx={{ justifyContent: 'flex-start', minWidth: 0, width: 'fit-content' }}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -675,7 +675,7 @@ export default function DashboardPage() {
|
|||||||
{project.slug} · updated {fmt(project.updated_at || project.created_at || 0)}
|
{project.slug} · updated {fmt(project.updated_at || project.created_at || 0)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Chip size="small" variant="outlined" label={project.home_page || 'info'} />
|
<Chip size="small" variant="outlined" label={project.home_page || 'settings'} />
|
||||||
</Box>
|
</Box>
|
||||||
))}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ function targetPath(projectId: string, homePage?: string) {
|
|||||||
if (homePage === 'issues') return `/projects/${projectId}/issues`
|
if (homePage === 'issues') return `/projects/${projectId}/issues`
|
||||||
if (homePage === 'wiki') return `/projects/${projectId}/wiki`
|
if (homePage === 'wiki') return `/projects/${projectId}/wiki`
|
||||||
if (homePage === 'files') return `/projects/${projectId}/files`
|
if (homePage === 'files') return `/projects/${projectId}/files`
|
||||||
return `/projects/${projectId}/info`
|
return `/projects/${projectId}/settings`
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ProjectEntryPage() {
|
export default function ProjectEntryPage() {
|
||||||
@@ -23,7 +23,7 @@ export default function ProjectEntryPage() {
|
|||||||
navigate(targetPath(projectId, project.home_page), { replace: true })
|
navigate(targetPath(projectId, project.home_page), { replace: true })
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
navigate(`/projects/${projectId}/info`, { replace: true })
|
navigate(`/projects/${projectId}/settings`, { replace: true })
|
||||||
})
|
})
|
||||||
}, [projectId, navigate])
|
}, [projectId, navigate])
|
||||||
|
|
||||||
|
|||||||
+21
-35
@@ -14,17 +14,17 @@ import DeleteIcon from '@mui/icons-material/Delete'
|
|||||||
import ConfirmDeleteDialog from '../components/ConfirmDeleteDialog'
|
import ConfirmDeleteDialog from '../components/ConfirmDeleteDialog'
|
||||||
import ProjectFormDialog from '../components/ProjectFormDialog'
|
import ProjectFormDialog from '../components/ProjectFormDialog'
|
||||||
import { ProjectDescriptionTab, ProjectHomePageValue } from '../components/ProjectFormDialog'
|
import { ProjectDescriptionTab, ProjectHomePageValue } from '../components/ProjectFormDialog'
|
||||||
import SelectField from '../components/SelectField'
|
|
||||||
import PageAlert from '../components/PageAlert'
|
import PageAlert from '../components/PageAlert'
|
||||||
|
import Autocomplete from '../components/Autocomplete'
|
||||||
|
|
||||||
export default function ProjectHomePage() {
|
export default function ProjectSettingsPage() {
|
||||||
const { projectId } = useParams()
|
const { projectId } = useParams()
|
||||||
const [project, setProject] = useState<Project | null>(null)
|
const [project, setProject] = useState<Project | null>(null)
|
||||||
const [editOpen, setEditOpen] = useState(false)
|
const [editOpen, setEditOpen] = useState(false)
|
||||||
const [editSlug, setEditSlug] = useState('')
|
const [editSlug, setEditSlug] = useState('')
|
||||||
const [editName, setEditName] = useState('')
|
const [editName, setEditName] = useState('')
|
||||||
const [editDescription, setEditDescription] = useState('')
|
const [editDescription, setEditDescription] = useState('')
|
||||||
const [editHomePage, setEditHomePage] = useState<ProjectHomePageValue>('info')
|
const [editHomePage, setEditHomePage] = useState<ProjectHomePageValue>('settings')
|
||||||
const [editDescTab, setEditDescTab] = useState<ProjectDescriptionTab>('write')
|
const [editDescTab, setEditDescTab] = useState<ProjectDescriptionTab>('write')
|
||||||
const [editError, setEditError] = useState<string | null>(null)
|
const [editError, setEditError] = useState<string | null>(null)
|
||||||
const [savingEdit, setSavingEdit] = useState(false)
|
const [savingEdit, setSavingEdit] = useState(false)
|
||||||
@@ -103,7 +103,7 @@ export default function ProjectHomePage() {
|
|||||||
setEditSlug(project.slug)
|
setEditSlug(project.slug)
|
||||||
setEditName(project.name)
|
setEditName(project.name)
|
||||||
setEditDescription(project.description || '')
|
setEditDescription(project.description || '')
|
||||||
setEditHomePage(project.home_page || 'info')
|
setEditHomePage(project.home_page || 'settings')
|
||||||
setEditDescTab('write')
|
setEditDescTab('write')
|
||||||
setEditError(null)
|
setEditError(null)
|
||||||
setEditOpen(true)
|
setEditOpen(true)
|
||||||
@@ -358,23 +358,16 @@ export default function ProjectHomePage() {
|
|||||||
actions={
|
actions={
|
||||||
canManageMembers ? (
|
canManageMembers ? (
|
||||||
<Box sx={{ display: 'flex', gap: 1, alignItems: 'center', flexWrap: 'wrap', justifyContent: 'flex-end' }}>
|
<Box sx={{ display: 'flex', gap: 1, alignItems: 'center', flexWrap: 'wrap', justifyContent: 'flex-end' }}>
|
||||||
<SelectField
|
<Autocomplete<User, false, false, false>
|
||||||
select
|
|
||||||
size="small"
|
size="small"
|
||||||
label="User"
|
options={memberUsers.filter((user: User) => !members.some((member: ProjectMember) => member.user_id === user.id))}
|
||||||
value={newMemberUserID}
|
value={memberUsers.find((user: User) => user.id === newMemberUserID) || null}
|
||||||
onChange={(event) => setNewMemberUserID(event.target.value)}
|
onChange={(_, value) => setNewMemberUserID(value?.id || '')}
|
||||||
|
getOptionLabel={(user: User) => user.display_name ? `${user.display_name} (${user.username})` : user.username}
|
||||||
|
isOptionEqualToValue={(option: User, value: User) => option.id === value.id}
|
||||||
sx={{ minWidth: 260 }}
|
sx={{ minWidth: 260 }}
|
||||||
>
|
renderInput={(params) => <TextField {...params} label="User" placeholder="Select user" />}
|
||||||
<MenuItem value="">Select user</MenuItem>
|
/>
|
||||||
{memberUsers
|
|
||||||
.filter((user) => !members.some((member) => member.user_id === user.id))
|
|
||||||
.map((user) => (
|
|
||||||
<MenuItem key={user.id} value={user.id}>
|
|
||||||
{user.display_name ? `${user.display_name} (${user.username})` : user.username}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</SelectField>
|
|
||||||
<ToggleButtonGroup
|
<ToggleButtonGroup
|
||||||
size="small"
|
size="small"
|
||||||
exclusive
|
exclusive
|
||||||
@@ -450,23 +443,16 @@ export default function ProjectHomePage() {
|
|||||||
actions={
|
actions={
|
||||||
canManageMembers ? (
|
canManageMembers ? (
|
||||||
<Box sx={{ display: 'flex', gap: 1, alignItems: 'center', flexWrap: 'wrap', justifyContent: 'flex-end' }}>
|
<Box sx={{ display: 'flex', gap: 1, alignItems: 'center', flexWrap: 'wrap', justifyContent: 'flex-end' }}>
|
||||||
<SelectField
|
<Autocomplete<UserGroup, false, false, false>
|
||||||
select
|
|
||||||
size="small"
|
size="small"
|
||||||
label="Group"
|
options={allGroups.filter((group: UserGroup) => !groupRoles.some((role: ProjectGroupRole) => role.group_id === group.id))}
|
||||||
value={newGroupRoleGroupID}
|
value={allGroups.find((group: UserGroup) => group.id === newGroupRoleGroupID) || null}
|
||||||
onChange={(event) => setNewGroupRoleGroupID(event.target.value)}
|
onChange={(_, value) => setNewGroupRoleGroupID(value?.id || '')}
|
||||||
sx={{ minWidth: 220 }}
|
getOptionLabel={(group: UserGroup) => group.name}
|
||||||
>
|
isOptionEqualToValue={(option: UserGroup, value: UserGroup) => option.id === value.id}
|
||||||
<MenuItem value="">Select group</MenuItem>
|
sx={{ minWidth: 260 }}
|
||||||
{allGroups
|
renderInput={(params) => <TextField {...params} label="Group" placeholder="Select group" />}
|
||||||
.filter((group) => !groupRoles.some((role) => role.group_id === group.id))
|
/>
|
||||||
.map((group) => (
|
|
||||||
<MenuItem key={group.id} value={group.id}>
|
|
||||||
{group.name}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</SelectField>
|
|
||||||
<ToggleButtonGroup
|
<ToggleButtonGroup
|
||||||
size="small"
|
size="small"
|
||||||
exclusive
|
exclusive
|
||||||
@@ -21,7 +21,7 @@ export default function ProjectsPage() {
|
|||||||
const [editSlug, setEditSlug] = useState('')
|
const [editSlug, setEditSlug] = useState('')
|
||||||
const [editName, setEditName] = useState('')
|
const [editName, setEditName] = useState('')
|
||||||
const [editDescription, setEditDescription] = useState('')
|
const [editDescription, setEditDescription] = useState('')
|
||||||
const [editHomePage, setEditHomePage] = useState<ProjectHomePageValue>('info')
|
const [editHomePage, setEditHomePage] = useState<ProjectHomePageValue>('settings')
|
||||||
const [editDescTab, setEditDescTab] = useState<ProjectDescriptionTab>('write')
|
const [editDescTab, setEditDescTab] = useState<ProjectDescriptionTab>('write')
|
||||||
const [editError, setEditError] = useState<string | null>(null)
|
const [editError, setEditError] = useState<string | null>(null)
|
||||||
const [createOpen, setCreateOpen] = useState(false)
|
const [createOpen, setCreateOpen] = useState(false)
|
||||||
@@ -30,7 +30,7 @@ export default function ProjectsPage() {
|
|||||||
const [createError, setCreateError] = useState<string | null>(null)
|
const [createError, setCreateError] = useState<string | null>(null)
|
||||||
const [creating, setCreating] = useState(false)
|
const [creating, setCreating] = useState(false)
|
||||||
const [createDescription, setCreateDescription] = useState('')
|
const [createDescription, setCreateDescription] = useState('')
|
||||||
const [createHomePage, setCreateHomePage] = useState<ProjectHomePageValue>('info')
|
const [createHomePage, setCreateHomePage] = useState<ProjectHomePageValue>('settings')
|
||||||
const [createDescTab, setCreateDescTab] = useState<ProjectDescriptionTab>('write')
|
const [createDescTab, setCreateDescTab] = useState<ProjectDescriptionTab>('write')
|
||||||
const [savingEdit, setSavingEdit] = useState(false)
|
const [savingEdit, setSavingEdit] = useState(false)
|
||||||
const [deleteProject, setDeleteProject] = useState<Project | null>(null)
|
const [deleteProject, setDeleteProject] = useState<Project | null>(null)
|
||||||
@@ -103,7 +103,7 @@ export default function ProjectsPage() {
|
|||||||
setCreateSlug('')
|
setCreateSlug('')
|
||||||
setCreateName('')
|
setCreateName('')
|
||||||
setCreateDescription('')
|
setCreateDescription('')
|
||||||
setCreateHomePage('info')
|
setCreateHomePage('settings')
|
||||||
setCreateDescTab('write')
|
setCreateDescTab('write')
|
||||||
setCreateOpen(false)
|
setCreateOpen(false)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -119,7 +119,7 @@ export default function ProjectsPage() {
|
|||||||
setEditSlug(project.slug)
|
setEditSlug(project.slug)
|
||||||
setEditName(project.name)
|
setEditName(project.name)
|
||||||
setEditDescription(project.description || '')
|
setEditDescription(project.description || '')
|
||||||
setEditHomePage(project.home_page || 'info')
|
setEditHomePage(project.home_page || 'settings')
|
||||||
setEditDescTab('write')
|
setEditDescTab('write')
|
||||||
setEditError(null)
|
setEditError(null)
|
||||||
}
|
}
|
||||||
@@ -145,7 +145,7 @@ export default function ProjectsPage() {
|
|||||||
setEditSlug('')
|
setEditSlug('')
|
||||||
setEditName('')
|
setEditName('')
|
||||||
setEditDescription('')
|
setEditDescription('')
|
||||||
setEditHomePage('info')
|
setEditHomePage('settings')
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const message = err instanceof Error ? err.message : 'Failed to update project'
|
const message = err instanceof Error ? err.message : 'Failed to update project'
|
||||||
setEditError(message)
|
setEditError(message)
|
||||||
@@ -213,7 +213,7 @@ export default function ProjectsPage() {
|
|||||||
setCreateSlug('')
|
setCreateSlug('')
|
||||||
setCreateName('')
|
setCreateName('')
|
||||||
setCreateDescription('')
|
setCreateDescription('')
|
||||||
setCreateHomePage('info')
|
setCreateHomePage('settings')
|
||||||
setCreateDescTab('write')
|
setCreateDescTab('write')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ export default function ReposPage() {
|
|||||||
const [projectEditSlug, setProjectEditSlug] = useState('')
|
const [projectEditSlug, setProjectEditSlug] = useState('')
|
||||||
const [projectEditName, setProjectEditName] = useState('')
|
const [projectEditName, setProjectEditName] = useState('')
|
||||||
const [projectEditDescription, setProjectEditDescription] = useState('')
|
const [projectEditDescription, setProjectEditDescription] = useState('')
|
||||||
const [projectEditHomePage, setProjectEditHomePage] = useState<ProjectHomePageValue>('info')
|
const [projectEditHomePage, setProjectEditHomePage] = useState<ProjectHomePageValue>('settings')
|
||||||
const [projectEditDescTab, setProjectEditDescTab] = useState<ProjectDescriptionTab>('write')
|
const [projectEditDescTab, setProjectEditDescTab] = useState<ProjectDescriptionTab>('write')
|
||||||
const [projectEditError, setProjectEditError] = useState<string | null>(null)
|
const [projectEditError, setProjectEditError] = useState<string | null>(null)
|
||||||
const [savingProjectEdit, setSavingProjectEdit] = useState(false)
|
const [savingProjectEdit, setSavingProjectEdit] = useState(false)
|
||||||
@@ -352,7 +352,7 @@ export default function ReposPage() {
|
|||||||
setProjectEditSlug(project.slug)
|
setProjectEditSlug(project.slug)
|
||||||
setProjectEditName(project.name)
|
setProjectEditName(project.name)
|
||||||
setProjectEditDescription(project.description || '')
|
setProjectEditDescription(project.description || '')
|
||||||
setProjectEditHomePage(project.home_page || 'info')
|
setProjectEditHomePage(project.home_page || 'settings')
|
||||||
setProjectEditDescTab('write')
|
setProjectEditDescTab('write')
|
||||||
setProjectEditError(null)
|
setProjectEditError(null)
|
||||||
setProjectEditOpen(true)
|
setProjectEditOpen(true)
|
||||||
|
|||||||
Reference in New Issue
Block a user