Compare commits
3 Commits
23f2f89a38
...
e375e79954
| Author | SHA1 | Date | |
|---|---|---|---|
| e375e79954 | |||
| 2e2251ee19 | |||
| 568230b966 |
@@ -1042,8 +1042,8 @@ func (s *Store) ListSSHAccessProfilesForUser(userID string) ([]models.SSHAccessP
|
||||
p.owner_scope = ?
|
||||
AND p.enabled = 1
|
||||
AND s.enabled = 1
|
||||
AND (p.valid_after = 0 OR p.valid_after <= strftime('%s','now'))
|
||||
AND (p.valid_before = 0 OR p.valid_before >= 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 >= CAST(strftime('%s','now') AS INTEGER))
|
||||
AND (
|
||||
(t.target_type = 'user' AND tu.public_id = ?)
|
||||
OR
|
||||
@@ -1234,9 +1234,9 @@ func (s *Store) GetSSHAccessProfileForUser(userID string, id string) (models.SSH
|
||||
p.owner_scope = ?
|
||||
AND p.enabled = 1
|
||||
AND s.enabled = 1
|
||||
AND (p.valid_after = 0 OR p.valid_after <= strftime('%s','now'))
|
||||
AND (p.valid_before = 0 OR p.valid_before >= strftime('%s','now'))
|
||||
AND (
|
||||
AND (p.valid_after = 0 OR p.valid_after <= CAST(strftime('%s','now') AS INTEGER))
|
||||
AND (p.valid_before = 0 OR p.valid_before >= CAST(strftime('%s','now') AS INTEGER))
|
||||
AND (
|
||||
(t.target_type = 'user' AND tu.public_id = ?)
|
||||
OR
|
||||
(t.target_type = 'group' AND ug.disabled = 0 AND (ug.scope = 'all_users' OR gu.public_id = ?))
|
||||
|
||||
+68
-155
@@ -11,7 +11,6 @@ import "codit/internal/util"
|
||||
func (s *Store) CreateUser(user models.User, passwordHash string) (models.User, error) {
|
||||
var id string
|
||||
var err error
|
||||
var now time.Time
|
||||
var nowUnix int64
|
||||
if user.ID == "" {
|
||||
id, err = util.NewID()
|
||||
@@ -20,44 +19,39 @@ func (s *Store) CreateUser(user models.User, passwordHash string) (models.User,
|
||||
}
|
||||
user.ID = id
|
||||
}
|
||||
now = time.Now().UTC()
|
||||
nowUnix = now.Unix()
|
||||
nowUnix = time.Now().UTC().Unix()
|
||||
user.CreatedAt = nowUnix
|
||||
user.UpdatedAt = nowUnix
|
||||
_, 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)
|
||||
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
|
||||
}
|
||||
|
||||
func (s *Store) UpdateUser(user models.User) error {
|
||||
var err error
|
||||
var now time.Time
|
||||
var nowUnix int64
|
||||
now = time.Now().UTC()
|
||||
nowUnix = now.Unix()
|
||||
nowUnix = time.Now().UTC().Unix()
|
||||
user.UpdatedAt = nowUnix
|
||||
_, 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
|
||||
}
|
||||
|
||||
func (s *Store) UpdateUserWithPassword(user models.User, passwordHash string) error {
|
||||
var err error
|
||||
var now time.Time
|
||||
var nowUnix int64
|
||||
var tx *sql.Tx
|
||||
var owned bool
|
||||
now = time.Now().UTC()
|
||||
nowUnix = now.Unix()
|
||||
nowUnix = time.Now().UTC().Unix()
|
||||
user.UpdatedAt = nowUnix
|
||||
tx, owned, err = s.begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, 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 {
|
||||
rollbackIfOwned(tx, owned)
|
||||
return err
|
||||
@@ -71,23 +65,19 @@ func (s *Store) UpdateUserWithPassword(user models.User, passwordHash string) er
|
||||
|
||||
func (s *Store) SetUserPassword(userID, passwordHash string) 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
|
||||
}
|
||||
|
||||
func (s *Store) GetUserByID(id string) (models.User, error) {
|
||||
var user models.User
|
||||
var row *sql.Row
|
||||
var created time.Time
|
||||
var updated time.Time
|
||||
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)
|
||||
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 {
|
||||
return user, err
|
||||
}
|
||||
user.CreatedAt = created.Unix()
|
||||
user.UpdatedAt = updated.Unix()
|
||||
return user, nil
|
||||
}
|
||||
|
||||
@@ -96,15 +86,11 @@ func (s *Store) GetUserByUsername(username string) (models.User, string, error)
|
||||
var passwordHash sql.NullString
|
||||
var row *sql.Row
|
||||
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)
|
||||
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 {
|
||||
return user, passwordHash.String, err
|
||||
}
|
||||
user.CreatedAt = created.Unix()
|
||||
user.UpdatedAt = updated.Unix()
|
||||
return user, passwordHash.String, nil
|
||||
}
|
||||
|
||||
@@ -113,20 +99,16 @@ func (s *Store) ListUsers() ([]models.User, error) {
|
||||
var err error
|
||||
var users []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`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
u.CreatedAt = created.Unix()
|
||||
u.UpdatedAt = updated.Unix()
|
||||
users = append(users, u)
|
||||
}
|
||||
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) {
|
||||
var user models.User
|
||||
var row *sql.Row
|
||||
var created time.Time
|
||||
var updated time.Time
|
||||
var err error
|
||||
row = s.QueryRow(`
|
||||
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 = ?
|
||||
`, strings.TrimSpace(providerPublicID), strings.TrimSpace(sub))
|
||||
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 {
|
||||
return user, err
|
||||
}
|
||||
user.CreatedAt = created.Unix()
|
||||
user.UpdatedAt = updated.Unix()
|
||||
return user, nil
|
||||
}
|
||||
|
||||
@@ -368,24 +346,20 @@ func splitCSVValue(value string) []string {
|
||||
|
||||
func (s *Store) SetUserDisabled(id string, disabled bool) error {
|
||||
var err error
|
||||
var now time.Time
|
||||
now = time.Now().UTC()
|
||||
_, err = s.Exec(`UPDATE users SET disabled = ?, updated_at = ? WHERE public_id = ?`, disabled, now, id)
|
||||
_, err = s.Exec(`UPDATE users SET disabled = ?, updated_at = ? WHERE public_id = ?`, disabled, time.Now().UTC().Unix(), id)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Store) CreateAPIKey(userID string, name string, tokenHash string, prefix string, expiresAt int64) (models.APIKey, error) {
|
||||
var key models.APIKey
|
||||
var err error
|
||||
var now time.Time
|
||||
var nowUnix int64
|
||||
var id string
|
||||
id, err = util.NewID()
|
||||
if err != nil {
|
||||
return key, err
|
||||
}
|
||||
now = time.Now().UTC()
|
||||
nowUnix = now.Unix()
|
||||
nowUnix = time.Now().UTC().Unix()
|
||||
key = models.APIKey{
|
||||
ID: id,
|
||||
UserID: userID,
|
||||
@@ -604,19 +578,14 @@ func (s *Store) GetUserByAPIKeyHash(tokenHash string) (models.User, error) {
|
||||
var tx *sql.Tx
|
||||
var owned bool
|
||||
var row *sql.Row
|
||||
var created time.Time
|
||||
var updated time.Time
|
||||
var keyID int64
|
||||
var now time.Time
|
||||
var nowUnix int64
|
||||
var err error
|
||||
var currentUnix int64
|
||||
tx, owned, err = s.begin()
|
||||
if err != nil {
|
||||
return user, err
|
||||
}
|
||||
now = time.Now().UTC()
|
||||
currentUnix = now.Unix()
|
||||
nowUnix = time.Now().UTC().Unix()
|
||||
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
|
||||
FROM api_keys k
|
||||
@@ -627,16 +596,13 @@ func (s *Store) GetUserByAPIKeyHash(tokenHash string) (models.User, error) {
|
||||
AND k.disabled = 0
|
||||
AND (k.expires_at = 0 OR k.expires_at > ?)
|
||||
LIMIT 1
|
||||
`, tokenHash, currentUnix)
|
||||
err = row.Scan(&user.ID, &user.Username, &user.DisplayName, &user.Email, &user.IsAdmin, &user.Disabled, &user.AuthProviderID, &created, &updated, &keyID)
|
||||
`, tokenHash, nowUnix)
|
||||
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 {
|
||||
rollbackIfOwned(tx, owned)
|
||||
return user, err
|
||||
}
|
||||
user.CreatedAt = created.Unix()
|
||||
user.UpdatedAt = updated.Unix()
|
||||
now = time.Now().UTC()
|
||||
nowUnix = now.Unix()
|
||||
nowUnix = time.Now().UTC().Unix()
|
||||
_, err = tx.Exec(`UPDATE api_keys SET last_used_at = ? WHERE id = ?`, nowUnix, keyID)
|
||||
if err != nil {
|
||||
rollbackIfOwned(tx, owned)
|
||||
@@ -653,7 +619,7 @@ func (s *Store) CreateSession(userID string, token string, expiresAt time.Time,
|
||||
var err error
|
||||
_, err = s.Exec(`INSERT INTO sessions (id, user_id, token, expires_at, created_at, totp_verified)
|
||||
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
|
||||
}
|
||||
|
||||
@@ -671,18 +637,16 @@ func (s *Store) DeleteSession(token string) error {
|
||||
|
||||
func (s *Store) DeleteExpiredSessions(now time.Time) 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
|
||||
}
|
||||
|
||||
func (s *Store) GetSessionUser(token string) (models.User, time.Time, bool, error) {
|
||||
var user models.User
|
||||
var expires time.Time
|
||||
var expiresUnix int64
|
||||
var totpVerified bool
|
||||
var row *sql.Row
|
||||
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, ''), COALESCE(t.enabled, 0), u.totp_required,
|
||||
(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
|
||||
WHERE s.token = ? AND u.disabled = 0
|
||||
`, 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 {
|
||||
return user, time.Time{}, false, err
|
||||
}
|
||||
user.CreatedAt = created.Unix()
|
||||
user.UpdatedAt = updated.Unix()
|
||||
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) {
|
||||
var id string
|
||||
var err error
|
||||
var now time.Time
|
||||
var nowUnix int64
|
||||
var tx *sql.Tx
|
||||
var owned bool
|
||||
@@ -722,8 +683,7 @@ func (s *Store) CreateProject(project models.Project) (models.Project, error) {
|
||||
}
|
||||
project.ID = id
|
||||
}
|
||||
now = time.Now().UTC()
|
||||
nowUnix = now.Unix()
|
||||
nowUnix = time.Now().UTC().Unix()
|
||||
project.CreatedAt = nowUnix
|
||||
project.UpdatedAt = nowUnix
|
||||
if project.UpdatedBy == "" {
|
||||
@@ -734,10 +694,10 @@ func (s *Store) CreateProject(project models.Project) (models.Project, error) {
|
||||
return project, err
|
||||
}
|
||||
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)
|
||||
VALUES (?, ?, ?, ?, ?, (SELECT id FROM users WHERE public_id = ?), (SELECT id FROM users WHERE public_id = ?), ?, ?, ?, ?)`,
|
||||
_, 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 = ?), ?, ?)`,
|
||||
project.ID,
|
||||
project.Slug,
|
||||
project.Name,
|
||||
@@ -745,8 +705,6 @@ func (s *Store) CreateProject(project models.Project) (models.Project, error) {
|
||||
project.HomePage,
|
||||
project.CreatedBy,
|
||||
project.UpdatedBy,
|
||||
now,
|
||||
now,
|
||||
project.CreatedAt,
|
||||
project.UpdatedAt,
|
||||
)
|
||||
@@ -771,16 +729,15 @@ func (s *Store) CreateProject(project models.Project) (models.Project, error) {
|
||||
func (s *Store) UpdateProject(project models.Project) error {
|
||||
var err error
|
||||
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.Name,
|
||||
project.Description,
|
||||
project.HomePage,
|
||||
time.Unix(project.UpdatedAt, 0).UTC(),
|
||||
project.UpdatedBy,
|
||||
project.UpdatedAt,
|
||||
project.UpdatedBy,
|
||||
project.ID,
|
||||
)
|
||||
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,
|
||||
c.public_id, u.public_id,
|
||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||
p.created_at_unix, p.updated_at_unix
|
||||
p.created_at, p.updated_at
|
||||
FROM projects p
|
||||
LEFT JOIN users c ON c.id = p.created_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,
|
||||
c.public_id, u.public_id,
|
||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||
p.created_at_unix, p.updated_at_unix
|
||||
p.created_at, p.updated_at
|
||||
FROM projects p
|
||||
LEFT JOIN users c ON c.id = p.created_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,
|
||||
c.public_id, u.public_id,
|
||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||
p.created_at_unix, p.updated_at_unix
|
||||
p.created_at, p.updated_at
|
||||
FROM projects p
|
||||
LEFT JOIN users c ON c.id = p.created_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,
|
||||
c.public_id, u.public_id,
|
||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||
p.created_at_unix, p.updated_at_unix
|
||||
p.created_at, p.updated_at
|
||||
FROM projects p
|
||||
LEFT JOIN users c ON c.id = p.created_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,
|
||||
c.public_id, u.public_id,
|
||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||
p.created_at_unix, p.updated_at_unix
|
||||
p.created_at, p.updated_at
|
||||
FROM projects p
|
||||
LEFT JOIN users c ON c.id = p.created_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,
|
||||
c.public_id, u.public_id,
|
||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||
p.created_at_unix, p.updated_at_unix
|
||||
p.created_at, p.updated_at
|
||||
FROM projects p
|
||||
LEFT JOIN users c ON c.id = p.created_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,
|
||||
c.public_id, u.public_id,
|
||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||
p.created_at_unix, p.updated_at_unix
|
||||
p.created_at, p.updated_at
|
||||
FROM projects p
|
||||
LEFT JOIN users c ON c.id = p.created_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,
|
||||
c.public_id, u.public_id,
|
||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||
p.created_at_unix, p.updated_at_unix
|
||||
p.created_at, p.updated_at
|
||||
FROM projects p
|
||||
LEFT JOIN users c ON c.id = p.created_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,
|
||||
c.public_id, u.public_id,
|
||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||
p.created_at_unix, p.updated_at_unix
|
||||
p.created_at, p.updated_at
|
||||
FROM projects p
|
||||
LEFT JOIN users c ON c.id = p.created_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,
|
||||
c.public_id, u.public_id,
|
||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||
p.created_at_unix, p.updated_at_unix
|
||||
p.created_at, p.updated_at
|
||||
FROM projects p
|
||||
LEFT JOIN users c ON c.id = p.created_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,
|
||||
c.public_id, u.public_id,
|
||||
COALESCE(c.username, ''), COALESCE(u.username, ''),
|
||||
p.created_at_unix, p.updated_at_unix
|
||||
p.created_at, p.updated_at
|
||||
FROM projects p
|
||||
LEFT JOIN users c ON c.id = p.created_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) {
|
||||
var id string
|
||||
var err error
|
||||
var now time.Time
|
||||
var nowUnix int64
|
||||
if repo.ID == "" {
|
||||
id, err = util.NewID()
|
||||
@@ -1506,12 +1462,11 @@ func (s *Store) CreateRepo(repo models.Repo) (models.Repo, error) {
|
||||
}
|
||||
repo.ID = id
|
||||
}
|
||||
now = time.Now().UTC()
|
||||
nowUnix = now.Unix()
|
||||
nowUnix = time.Now().UTC().Unix()
|
||||
repo.CreatedAt = nowUnix
|
||||
_, 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 = ?), ?)`,
|
||||
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
|
||||
}
|
||||
|
||||
@@ -1532,18 +1487,16 @@ func (s *Store) RepoNameExists(projectID string, name string, repoType string) (
|
||||
func (s *Store) GetRepo(id string) (models.Repo, error) {
|
||||
var repo models.Repo
|
||||
var row *sql.Row
|
||||
var created time.Time
|
||||
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
|
||||
FROM repos r
|
||||
JOIN projects p ON p.id = r.project_id
|
||||
JOIN users u ON u.id = r.created_by
|
||||
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 {
|
||||
return repo, err
|
||||
}
|
||||
repo.CreatedAt = created.Unix()
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
@@ -1567,7 +1520,6 @@ func (s *Store) GetRepoByProjectNameType(projectID string, name string, repoType
|
||||
var repo models.Repo
|
||||
var row *sql.Row
|
||||
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
|
||||
FROM repos r
|
||||
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 = ?)
|
||||
AND r.name = ? AND r.type = ?`,
|
||||
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 {
|
||||
return repo, err
|
||||
}
|
||||
repo.CreatedAt = created.Unix()
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
@@ -1589,7 +1540,6 @@ func (s *Store) ListRepos(projectID string) ([]models.Repo, error) {
|
||||
var repos []models.Repo
|
||||
var r models.Repo
|
||||
var isForeign int
|
||||
var created time.Time
|
||||
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
|
||||
FROM repos r
|
||||
@@ -1611,11 +1561,10 @@ func (s *Store) ListRepos(projectID string) ([]models.Repo, error) {
|
||||
}
|
||||
defer rows.Close()
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
r.CreatedAt = created.Unix()
|
||||
r.IsForeign = isForeign != 0
|
||||
repos = append(repos, r)
|
||||
}
|
||||
@@ -1627,7 +1576,6 @@ func (s *Store) ListReposOwned(projectID string) ([]models.Repo, error) {
|
||||
var err error
|
||||
var repos []models.Repo
|
||||
var r models.Repo
|
||||
var created time.Time
|
||||
rows, err = s.Query(`
|
||||
SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at
|
||||
FROM repos r
|
||||
@@ -1641,11 +1589,10 @@ func (s *Store) ListReposOwned(projectID string) ([]models.Repo, error) {
|
||||
}
|
||||
defer rows.Close()
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
r.CreatedAt = created.Unix()
|
||||
repos = append(repos, r)
|
||||
}
|
||||
return repos, rows.Err()
|
||||
@@ -1656,7 +1603,6 @@ func (s *Store) ListAllRepos() ([]models.Repo, error) {
|
||||
var err error
|
||||
var repos []models.Repo
|
||||
var r models.Repo
|
||||
var created time.Time
|
||||
rows, err = s.Query(`
|
||||
SELECT r.public_id, p.public_id, r.name, r.type, r.path, u.public_id, r.created_at
|
||||
FROM repos r
|
||||
@@ -1669,11 +1615,10 @@ func (s *Store) ListAllRepos() ([]models.Repo, error) {
|
||||
}
|
||||
defer rows.Close()
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
r.CreatedAt = created.Unix()
|
||||
repos = append(repos, r)
|
||||
}
|
||||
return repos, rows.Err()
|
||||
@@ -1684,7 +1629,6 @@ func (s *Store) ListReposByProjectIDs(projectIDs []string) ([]models.Repo, error
|
||||
var err error
|
||||
var repos []models.Repo
|
||||
var r models.Repo
|
||||
var created time.Time
|
||||
var placeholders []string
|
||||
var args []interface{}
|
||||
var i int
|
||||
@@ -1715,11 +1659,10 @@ func (s *Store) ListReposByProjectIDs(projectIDs []string) ([]models.Repo, error
|
||||
}
|
||||
defer rows.Close()
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
r.CreatedAt = created.Unix()
|
||||
repos = append(repos, r)
|
||||
}
|
||||
return repos, rows.Err()
|
||||
@@ -1781,7 +1724,7 @@ func (s *Store) AttachRepoToProject(projectID string, repoID string) error {
|
||||
var err error
|
||||
_, 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 = ?), ?)`,
|
||||
projectID, repoID, time.Now().UTC())
|
||||
projectID, repoID, time.Now().UTC().Unix())
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1825,7 +1768,6 @@ func (s *Store) ListAvailableReposForProject(projectID string, query string, lim
|
||||
var err error
|
||||
var repos []models.Repo
|
||||
var r models.Repo
|
||||
var created time.Time
|
||||
if limit <= 0 {
|
||||
limit = 100
|
||||
}
|
||||
@@ -1871,11 +1813,10 @@ func (s *Store) ListAvailableReposForProject(projectID string, query string, lim
|
||||
}
|
||||
defer rows.Close()
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
r.CreatedAt = created.Unix()
|
||||
r.IsForeign = false
|
||||
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) {
|
||||
var id string
|
||||
var err error
|
||||
var now time.Time
|
||||
var nowUnix int64
|
||||
if issue.ID == "" {
|
||||
id, err = util.NewID()
|
||||
@@ -1894,8 +1834,7 @@ func (s *Store) CreateIssue(issue models.Issue) (models.Issue, error) {
|
||||
}
|
||||
issue.ID = id
|
||||
}
|
||||
now = time.Now().UTC()
|
||||
nowUnix = now.Unix()
|
||||
nowUnix = time.Now().UTC().Unix()
|
||||
issue.CreatedAt = nowUnix
|
||||
issue.UpdatedAt = nowUnix
|
||||
if issue.Status == "" {
|
||||
@@ -1904,27 +1843,23 @@ func (s *Store) CreateIssue(issue models.Issue) (models.Issue, error) {
|
||||
_, err = s.Exec(`
|
||||
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 = ?), ?, ?)
|
||||
`, 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
|
||||
}
|
||||
|
||||
func (s *Store) UpdateIssue(issue models.Issue) error {
|
||||
var err error
|
||||
var now time.Time
|
||||
var nowUnix int64
|
||||
now = time.Now().UTC()
|
||||
nowUnix = now.Unix()
|
||||
nowUnix = time.Now().UTC().Unix()
|
||||
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 = ?`,
|
||||
issue.Title, issue.Body, issue.Status, issue.AssigneeID, now, issue.ID)
|
||||
issue.Title, issue.Body, issue.Status, issue.AssigneeID, nowUnix, issue.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Store) GetIssue(id string) (models.Issue, error) {
|
||||
var issue models.Issue
|
||||
var row *sql.Row
|
||||
var created time.Time
|
||||
var updated time.Time
|
||||
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
|
||||
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
|
||||
LEFT JOIN users au ON au.id = i.assignee_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 {
|
||||
return issue, err
|
||||
}
|
||||
issue.CreatedAt = created.Unix()
|
||||
issue.UpdatedAt = updated.Unix()
|
||||
return issue, nil
|
||||
}
|
||||
|
||||
@@ -1946,8 +1879,6 @@ func (s *Store) ListIssues(projectID string) ([]models.Issue, error) {
|
||||
var err error
|
||||
var issues []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
|
||||
FROM issues i
|
||||
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()
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
issue.CreatedAt = created.Unix()
|
||||
issue.UpdatedAt = updated.Unix()
|
||||
issues = append(issues, issue)
|
||||
}
|
||||
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) {
|
||||
var id string
|
||||
var err error
|
||||
var now time.Time
|
||||
var nowUnix int64
|
||||
if comment.ID == "" {
|
||||
id, err = util.NewID()
|
||||
@@ -1983,19 +1911,17 @@ func (s *Store) AddIssueComment(comment models.IssueComment) (models.IssueCommen
|
||||
}
|
||||
comment.ID = id
|
||||
}
|
||||
now = time.Now().UTC()
|
||||
nowUnix = now.Unix()
|
||||
nowUnix = time.Now().UTC().Unix()
|
||||
comment.CreatedAt = nowUnix
|
||||
_, 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 = ?), ?)`,
|
||||
comment.ID, comment.IssueID, comment.Body, comment.CreatedBy, now)
|
||||
comment.ID, comment.IssueID, comment.Body, comment.CreatedBy, nowUnix)
|
||||
return comment, err
|
||||
}
|
||||
|
||||
func (s *Store) CreateWikiPage(page models.WikiPage) (models.WikiPage, error) {
|
||||
var id string
|
||||
var err error
|
||||
var now time.Time
|
||||
var nowUnix int64
|
||||
if page.ID == "" {
|
||||
id, err = util.NewID()
|
||||
@@ -2004,23 +1930,20 @@ func (s *Store) CreateWikiPage(page models.WikiPage) (models.WikiPage, error) {
|
||||
}
|
||||
page.ID = id
|
||||
}
|
||||
now = time.Now().UTC()
|
||||
nowUnix = now.Unix()
|
||||
nowUnix = time.Now().UTC().Unix()
|
||||
page.UpdatedAt = nowUnix
|
||||
_, 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 = ?), ?)`,
|
||||
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
|
||||
}
|
||||
|
||||
func (s *Store) UpdateWikiPage(page models.WikiPage) error {
|
||||
var err error
|
||||
var now time.Time
|
||||
var nowUnix int64
|
||||
now = time.Now().UTC()
|
||||
nowUnix = now.Unix()
|
||||
nowUnix = time.Now().UTC().Unix()
|
||||
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
|
||||
}
|
||||
|
||||
@@ -2029,7 +1952,6 @@ func (s *Store) ListWikiPages(projectID string) ([]models.WikiPage, error) {
|
||||
var err error
|
||||
var pages []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
|
||||
FROM wiki_pages w
|
||||
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()
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
page.UpdatedAt = updated.Unix()
|
||||
pages = append(pages, page)
|
||||
}
|
||||
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) {
|
||||
var page models.WikiPage
|
||||
var row *sql.Row
|
||||
var updated time.Time
|
||||
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
|
||||
FROM wiki_pages w
|
||||
JOIN projects p ON p.id = w.project_id
|
||||
JOIN users u ON u.id = w.created_by
|
||||
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 {
|
||||
return page, err
|
||||
}
|
||||
page.UpdatedAt = updated.Unix()
|
||||
return page, nil
|
||||
}
|
||||
|
||||
func (s *Store) CreateUpload(upload models.Upload) (models.Upload, error) {
|
||||
var id string
|
||||
var err error
|
||||
var now time.Time
|
||||
var nowUnix int64
|
||||
if upload.ID == "" {
|
||||
id, err = util.NewID()
|
||||
@@ -2081,30 +1999,27 @@ func (s *Store) CreateUpload(upload models.Upload) (models.Upload, error) {
|
||||
}
|
||||
upload.ID = id
|
||||
}
|
||||
now = time.Now().UTC()
|
||||
nowUnix = now.Unix()
|
||||
nowUnix = time.Now().UTC().Unix()
|
||||
upload.CreatedAt = nowUnix
|
||||
_, 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 = ?), ?)`,
|
||||
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
|
||||
}
|
||||
|
||||
func (s *Store) GetUpload(id string) (models.Upload, error) {
|
||||
var upload models.Upload
|
||||
var row *sql.Row
|
||||
var created time.Time
|
||||
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
|
||||
FROM uploads up
|
||||
JOIN projects p ON p.id = up.project_id
|
||||
JOIN users u ON u.id = up.created_by
|
||||
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 {
|
||||
return upload, err
|
||||
}
|
||||
upload.CreatedAt = created.Unix()
|
||||
return upload, nil
|
||||
}
|
||||
|
||||
@@ -2113,7 +2028,6 @@ func (s *Store) ListUploads(projectID string) ([]models.Upload, error) {
|
||||
var err error
|
||||
var uploads []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
|
||||
FROM uploads up
|
||||
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()
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
upload.CreatedAt = created.Unix()
|
||||
uploads = append(uploads, upload)
|
||||
}
|
||||
return uploads, rows.Err()
|
||||
|
||||
@@ -14,20 +14,16 @@ type UserTOTP struct {
|
||||
func (s *Store) GetUserTOTP(userID string) (UserTOTP, error) {
|
||||
var item UserTOTP
|
||||
var row *sql.Row
|
||||
var created time.Time
|
||||
var updated time.Time
|
||||
var err error
|
||||
row = s.QueryRow(`
|
||||
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
|
||||
WHERE u.public_id = ?
|
||||
`, 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 {
|
||||
return item, err
|
||||
}
|
||||
item.CreatedAt = created.Unix()
|
||||
item.UpdatedAt = updated.Unix()
|
||||
return item, nil
|
||||
}
|
||||
|
||||
@@ -52,25 +48,25 @@ func (s *Store) UserRequiresTOTP(userID string) (bool, error) {
|
||||
|
||||
func (s *Store) UpsertUserTOTPPending(userID string, pendingSecretEncrypted string) error {
|
||||
var err error
|
||||
var now time.Time
|
||||
now = time.Now().UTC()
|
||||
var nowUnix int64
|
||||
nowUnix = time.Now().UTC().Unix()
|
||||
_, err = s.Exec(`
|
||||
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, ?, ?)
|
||||
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
|
||||
}
|
||||
|
||||
func (s *Store) EnableUserTOTP(userID string, secretEncrypted string) error {
|
||||
var err error
|
||||
var now time.Time
|
||||
now = time.Now().UTC()
|
||||
var nowUnix int64
|
||||
nowUnix = time.Now().UTC().Unix()
|
||||
_, err = s.Exec(`
|
||||
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, ?, ?)
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -1815,7 +1815,7 @@ func (api *API) UpdateProject(w http.ResponseWriter, r *http.Request, params map
|
||||
project.HomePage = normalizeProjectHomePage(req.HomePage)
|
||||
}
|
||||
if project.HomePage == "" {
|
||||
project.HomePage = "info"
|
||||
project.HomePage = "settings"
|
||||
}
|
||||
user, _ = middleware.UserFromContext(r.Context())
|
||||
project.UpdatedBy = user.ID
|
||||
@@ -5448,10 +5448,13 @@ func normalizeRole(role string) string {
|
||||
func normalizeProjectHomePage(value string) string {
|
||||
var v string
|
||||
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 "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")
|
||||
return
|
||||
}
|
||||
if !profile.Server.Enabled {
|
||||
WriteJSONWithErrorReason(w, r, http.StatusBadRequest, "ssh server is disabled")
|
||||
return
|
||||
}
|
||||
item = models.SSHSession{
|
||||
ProfileID: profile.ID,
|
||||
ServerID: profile.ServerID,
|
||||
|
||||
@@ -9,15 +9,15 @@ func TestUserJSONTags(t *testing.T) {
|
||||
var err error
|
||||
var decoded map[string]interface{}
|
||||
u = User{
|
||||
ID: "u1",
|
||||
Username: "alice",
|
||||
DisplayName: "Alice",
|
||||
Email: "a@x",
|
||||
IsAdmin: true,
|
||||
Disabled: true,
|
||||
AuthSource: "db",
|
||||
CreatedAt: 1,
|
||||
UpdatedAt: 2,
|
||||
ID: "u1",
|
||||
Username: "alice",
|
||||
DisplayName: "Alice",
|
||||
Email: "a@x",
|
||||
IsAdmin: true,
|
||||
Disabled: true,
|
||||
AuthProviderID: "p1",
|
||||
CreatedAt: 1,
|
||||
UpdatedAt: 2,
|
||||
}
|
||||
data, err = json.Marshal(u)
|
||||
if err != nil {
|
||||
@@ -37,6 +37,9 @@ func TestUserJSONTags(t *testing.T) {
|
||||
if _, ok := decoded["disabled"]; !ok {
|
||||
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) {
|
||||
|
||||
@@ -41,7 +41,7 @@ CREATE TABLE IF NOT EXISTS projects (
|
||||
slug TEXT NOT NULL UNIQUE,
|
||||
name 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,
|
||||
updated_by INTEGER NOT NULL DEFAULT 0,
|
||||
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;
|
||||
@@ -39,12 +39,12 @@ func createTestUser(t *testing.T, store *db.Store, username string) models.User
|
||||
t.Fatalf("hash password: %v", err)
|
||||
}
|
||||
user = models.User{
|
||||
Username: username,
|
||||
DisplayName: username,
|
||||
Email: username + "@local",
|
||||
IsAdmin: false,
|
||||
Disabled: false,
|
||||
AuthSource: "db",
|
||||
Username: username,
|
||||
DisplayName: username,
|
||||
Email: username + "@local",
|
||||
IsAdmin: false,
|
||||
Disabled: false,
|
||||
AuthProviderID: "",
|
||||
}
|
||||
user, err = store.CreateUser(user, passwordHash)
|
||||
if err != nil {
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ export interface Project {
|
||||
slug: string
|
||||
name: string
|
||||
description: string
|
||||
home_page?: 'info' | 'repos' | 'issues' | 'wiki' | 'files'
|
||||
home_page?: 'settings' | 'repos' | 'issues' | 'wiki' | 'files'
|
||||
created_by?: string
|
||||
updated_by?: string
|
||||
created_by_name?: string
|
||||
|
||||
@@ -8,7 +8,7 @@ import LoginPage from '../pages/LoginPage'
|
||||
import ProjectsPage from '../pages/ProjectsPage'
|
||||
import GlobalReposPage from '../pages/GlobalReposPage'
|
||||
import ProjectEntryPage from '../pages/ProjectEntryPage'
|
||||
import ProjectHomePage from '../pages/ProjectHomePage'
|
||||
import ProjectSettingsPage from '../pages/ProjectSettingsPage'
|
||||
import ReposPage from '../pages/ReposPage'
|
||||
import AdminUsersPage from '../pages/AdminUsersPage'
|
||||
import AdminUserGroupsPage from '../pages/AdminUserGroupsPage'
|
||||
@@ -87,7 +87,7 @@ export const routes: RouteObject[] = [
|
||||
)
|
||||
},
|
||||
{ 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/:repoId', element: withRouteSuspense(<RepoDetailPage />) },
|
||||
{ path: 'projects/:projectId/repos/:repoId/branches', element: withRouteSuspense(<BranchesPage />) },
|
||||
|
||||
@@ -15,7 +15,7 @@ import remarkGfm from 'remark-gfm'
|
||||
import FormDialogContent from './FormDialogContent'
|
||||
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'
|
||||
|
||||
type ProjectFormDialogProps = {
|
||||
@@ -76,7 +76,7 @@ export default function ProjectFormDialog(props: ProjectFormDialogProps) {
|
||||
<MenuItem value="issues">Issues</MenuItem>
|
||||
<MenuItem value="wiki">Wiki</MenuItem>
|
||||
<MenuItem value="files">Files</MenuItem>
|
||||
<MenuItem value="info">Settings</MenuItem>
|
||||
<MenuItem value="settings">Settings</MenuItem>
|
||||
</SelectField>
|
||||
<Box sx={{ mt: 1 }}>
|
||||
<Tabs
|
||||
|
||||
@@ -76,7 +76,7 @@ export default function ProjectNavBar(props: ProjectNavBarProps) {
|
||||
</Button>
|
||||
<Button
|
||||
component={Link}
|
||||
to={`/projects/${projectId}/info`}
|
||||
to={`/projects/${projectId}/settings`}
|
||||
startIcon={<InfoOutlinedIcon />}
|
||||
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)}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Chip size="small" variant="outlined" label={project.home_page || 'info'} />
|
||||
<Chip size="small" variant="outlined" label={project.home_page || 'settings'} />
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
|
||||
@@ -8,7 +8,7 @@ function targetPath(projectId: string, homePage?: string) {
|
||||
if (homePage === 'issues') return `/projects/${projectId}/issues`
|
||||
if (homePage === 'wiki') return `/projects/${projectId}/wiki`
|
||||
if (homePage === 'files') return `/projects/${projectId}/files`
|
||||
return `/projects/${projectId}/info`
|
||||
return `/projects/${projectId}/settings`
|
||||
}
|
||||
|
||||
export default function ProjectEntryPage() {
|
||||
@@ -23,7 +23,7 @@ export default function ProjectEntryPage() {
|
||||
navigate(targetPath(projectId, project.home_page), { replace: true })
|
||||
})
|
||||
.catch(() => {
|
||||
navigate(`/projects/${projectId}/info`, { replace: true })
|
||||
navigate(`/projects/${projectId}/settings`, { replace: true })
|
||||
})
|
||||
}, [projectId, navigate])
|
||||
|
||||
|
||||
+21
-35
@@ -14,17 +14,17 @@ import DeleteIcon from '@mui/icons-material/Delete'
|
||||
import ConfirmDeleteDialog from '../components/ConfirmDeleteDialog'
|
||||
import ProjectFormDialog from '../components/ProjectFormDialog'
|
||||
import { ProjectDescriptionTab, ProjectHomePageValue } from '../components/ProjectFormDialog'
|
||||
import SelectField from '../components/SelectField'
|
||||
import PageAlert from '../components/PageAlert'
|
||||
import Autocomplete from '../components/Autocomplete'
|
||||
|
||||
export default function ProjectHomePage() {
|
||||
export default function ProjectSettingsPage() {
|
||||
const { projectId } = useParams()
|
||||
const [project, setProject] = useState<Project | null>(null)
|
||||
const [editOpen, setEditOpen] = useState(false)
|
||||
const [editSlug, setEditSlug] = useState('')
|
||||
const [editName, setEditName] = useState('')
|
||||
const [editDescription, setEditDescription] = useState('')
|
||||
const [editHomePage, setEditHomePage] = useState<ProjectHomePageValue>('info')
|
||||
const [editHomePage, setEditHomePage] = useState<ProjectHomePageValue>('settings')
|
||||
const [editDescTab, setEditDescTab] = useState<ProjectDescriptionTab>('write')
|
||||
const [editError, setEditError] = useState<string | null>(null)
|
||||
const [savingEdit, setSavingEdit] = useState(false)
|
||||
@@ -103,7 +103,7 @@ export default function ProjectHomePage() {
|
||||
setEditSlug(project.slug)
|
||||
setEditName(project.name)
|
||||
setEditDescription(project.description || '')
|
||||
setEditHomePage(project.home_page || 'info')
|
||||
setEditHomePage(project.home_page || 'settings')
|
||||
setEditDescTab('write')
|
||||
setEditError(null)
|
||||
setEditOpen(true)
|
||||
@@ -358,23 +358,16 @@ export default function ProjectHomePage() {
|
||||
actions={
|
||||
canManageMembers ? (
|
||||
<Box sx={{ display: 'flex', gap: 1, alignItems: 'center', flexWrap: 'wrap', justifyContent: 'flex-end' }}>
|
||||
<SelectField
|
||||
select
|
||||
<Autocomplete<User, false, false, false>
|
||||
size="small"
|
||||
label="User"
|
||||
value={newMemberUserID}
|
||||
onChange={(event) => setNewMemberUserID(event.target.value)}
|
||||
options={memberUsers.filter((user: User) => !members.some((member: ProjectMember) => member.user_id === user.id))}
|
||||
value={memberUsers.find((user: User) => user.id === newMemberUserID) || null}
|
||||
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 }}
|
||||
>
|
||||
<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>
|
||||
renderInput={(params) => <TextField {...params} label="User" placeholder="Select user" />}
|
||||
/>
|
||||
<ToggleButtonGroup
|
||||
size="small"
|
||||
exclusive
|
||||
@@ -450,23 +443,16 @@ export default function ProjectHomePage() {
|
||||
actions={
|
||||
canManageMembers ? (
|
||||
<Box sx={{ display: 'flex', gap: 1, alignItems: 'center', flexWrap: 'wrap', justifyContent: 'flex-end' }}>
|
||||
<SelectField
|
||||
select
|
||||
<Autocomplete<UserGroup, false, false, false>
|
||||
size="small"
|
||||
label="Group"
|
||||
value={newGroupRoleGroupID}
|
||||
onChange={(event) => setNewGroupRoleGroupID(event.target.value)}
|
||||
sx={{ minWidth: 220 }}
|
||||
>
|
||||
<MenuItem value="">Select group</MenuItem>
|
||||
{allGroups
|
||||
.filter((group) => !groupRoles.some((role) => role.group_id === group.id))
|
||||
.map((group) => (
|
||||
<MenuItem key={group.id} value={group.id}>
|
||||
{group.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</SelectField>
|
||||
options={allGroups.filter((group: UserGroup) => !groupRoles.some((role: ProjectGroupRole) => role.group_id === group.id))}
|
||||
value={allGroups.find((group: UserGroup) => group.id === newGroupRoleGroupID) || null}
|
||||
onChange={(_, value) => setNewGroupRoleGroupID(value?.id || '')}
|
||||
getOptionLabel={(group: UserGroup) => group.name}
|
||||
isOptionEqualToValue={(option: UserGroup, value: UserGroup) => option.id === value.id}
|
||||
sx={{ minWidth: 260 }}
|
||||
renderInput={(params) => <TextField {...params} label="Group" placeholder="Select group" />}
|
||||
/>
|
||||
<ToggleButtonGroup
|
||||
size="small"
|
||||
exclusive
|
||||
@@ -21,7 +21,7 @@ export default function ProjectsPage() {
|
||||
const [editSlug, setEditSlug] = useState('')
|
||||
const [editName, setEditName] = useState('')
|
||||
const [editDescription, setEditDescription] = useState('')
|
||||
const [editHomePage, setEditHomePage] = useState<ProjectHomePageValue>('info')
|
||||
const [editHomePage, setEditHomePage] = useState<ProjectHomePageValue>('settings')
|
||||
const [editDescTab, setEditDescTab] = useState<ProjectDescriptionTab>('write')
|
||||
const [editError, setEditError] = useState<string | null>(null)
|
||||
const [createOpen, setCreateOpen] = useState(false)
|
||||
@@ -30,7 +30,7 @@ export default function ProjectsPage() {
|
||||
const [createError, setCreateError] = useState<string | null>(null)
|
||||
const [creating, setCreating] = useState(false)
|
||||
const [createDescription, setCreateDescription] = useState('')
|
||||
const [createHomePage, setCreateHomePage] = useState<ProjectHomePageValue>('info')
|
||||
const [createHomePage, setCreateHomePage] = useState<ProjectHomePageValue>('settings')
|
||||
const [createDescTab, setCreateDescTab] = useState<ProjectDescriptionTab>('write')
|
||||
const [savingEdit, setSavingEdit] = useState(false)
|
||||
const [deleteProject, setDeleteProject] = useState<Project | null>(null)
|
||||
@@ -103,7 +103,7 @@ export default function ProjectsPage() {
|
||||
setCreateSlug('')
|
||||
setCreateName('')
|
||||
setCreateDescription('')
|
||||
setCreateHomePage('info')
|
||||
setCreateHomePage('settings')
|
||||
setCreateDescTab('write')
|
||||
setCreateOpen(false)
|
||||
} catch (err) {
|
||||
@@ -119,7 +119,7 @@ export default function ProjectsPage() {
|
||||
setEditSlug(project.slug)
|
||||
setEditName(project.name)
|
||||
setEditDescription(project.description || '')
|
||||
setEditHomePage(project.home_page || 'info')
|
||||
setEditHomePage(project.home_page || 'settings')
|
||||
setEditDescTab('write')
|
||||
setEditError(null)
|
||||
}
|
||||
@@ -145,7 +145,7 @@ export default function ProjectsPage() {
|
||||
setEditSlug('')
|
||||
setEditName('')
|
||||
setEditDescription('')
|
||||
setEditHomePage('info')
|
||||
setEditHomePage('settings')
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : 'Failed to update project'
|
||||
setEditError(message)
|
||||
@@ -213,7 +213,7 @@ export default function ProjectsPage() {
|
||||
setCreateSlug('')
|
||||
setCreateName('')
|
||||
setCreateDescription('')
|
||||
setCreateHomePage('info')
|
||||
setCreateHomePage('settings')
|
||||
setCreateDescTab('write')
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ export default function ReposPage() {
|
||||
const [projectEditSlug, setProjectEditSlug] = useState('')
|
||||
const [projectEditName, setProjectEditName] = useState('')
|
||||
const [projectEditDescription, setProjectEditDescription] = useState('')
|
||||
const [projectEditHomePage, setProjectEditHomePage] = useState<ProjectHomePageValue>('info')
|
||||
const [projectEditHomePage, setProjectEditHomePage] = useState<ProjectHomePageValue>('settings')
|
||||
const [projectEditDescTab, setProjectEditDescTab] = useState<ProjectDescriptionTab>('write')
|
||||
const [projectEditError, setProjectEditError] = useState<string | null>(null)
|
||||
const [savingProjectEdit, setSavingProjectEdit] = useState(false)
|
||||
@@ -352,7 +352,7 @@ export default function ReposPage() {
|
||||
setProjectEditSlug(project.slug)
|
||||
setProjectEditName(project.name)
|
||||
setProjectEditDescription(project.description || '')
|
||||
setProjectEditHomePage(project.home_page || 'info')
|
||||
setProjectEditHomePage(project.home_page || 'settings')
|
||||
setProjectEditDescTab('write')
|
||||
setProjectEditError(null)
|
||||
setProjectEditOpen(true)
|
||||
|
||||
Reference in New Issue
Block a user