-
Notifications
You must be signed in to change notification settings - Fork 79
Feat: Add authentication methods #83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 4 commits
Commits
Show all changes
48 commits
Select commit
Hold shift + click to select a range
f68f002
fix: remove ProjectSectionNavChevron ('>' button) from all project pa…
nazarli-shabnam 1002dfd
feat: implement auth ui pages with better ui(LoginPage,SignUpPage,For…
nazarli-shabnam 9039940
refactor: Update auth, handler, model and 6 related areas for API and ui
nazarli-shabnam a909850
feat: add password_reset_tokens table with user_id, oken, and expire…
nazarli-shabnam 89140d3
fix: linting
nazarli-shabnam cc3cc1a
refactor: update api, auth, handler, mail, middleware for API and ui
nazarli-shabnam f04b46a
feat(auth): add password_reset_tokens table for user password reset f…
nazarli-shabnam 5558a5a
Merge branch '80-fix-create-views-buttons' of https://github.com/Devl…
nazarli-shabnam 7310246
refactor(routing): remove forgot and reset password page routes
nazarli-shabnam adaef29
refactor: update api, auth, config, handler, model for API and ui
nazarli-shabnam b066032
feat(db): create accounts table to store user provider connections
nazarli-shabnam 0ab34c3
feat(api): add auth for API
nazarli-shabnam 109febb
feat(deps): add glebarez/sqlite dependency for sqlite database support
nazarli-shabnam ec83439
feat(auth): add env vars for google oauth and magic code login, updat…
nazarli-shabnam db325dc
feat(auth): add SignUpMagic and SessionForEmailUser to enable magic l…
nazarli-shabnam 29a019a
refactor(ui): update api, instance-admin, pages, services for ui
nazarli-shabnam c2caeb8
feat(auth): introduce email magic code login/signup and API public UR…
nazarli-shabnam f4b111a
feat(auth): add email login magic code support and improve secret dec…
nazarli-shabnam b60122c
style(login): improve code formatting for readability
nazarli-shabnam 37af3d7
chore(merge): bring sticky-notes updates into forgot-password branch
nazarli-shabnam 51275b0
Merge remote-tracking branch 'origin/main' into forgot-password-in-login
nazarli-shabnam c36c5da
feat: all three edit pages (Google, GitHub, GitLab
nazarli-shabnam 77d4939
feat: removed OAuthRedirectBase from AuthHandler
nazarli-shabnam a70ac2d
refactor: update auth, handler, router, contexts for API and ui
nazarli-shabnam 488f8c9
refactor: replace the invite handling + ensureDefaultWorkspace with t…
nazarli-shabnam 9dc0bc1
refactor: update RootRedirect to handle the 'no workspaces' case prop…
nazarli-shabnam 53d50e2
chore: linting checks
nazarli-shabnam d3a16cf
chore: husky fixture
nazarli-shabnam 361e34f
feat: set-password UI page
nazarli-shabnam 07d2db6
feat: return distinct error for deactivated users
nazarli-shabnam dd703c9
feat: informational message when SMTP is off
nazarli-shabnam 05716c8
fix: copilot warnings
nazarli-shabnam 9f2ac4b
fix: persist organization size and harden auth migration
nazarli-shabnam 6dd21d0
Merge branch 'main' of https://github.com/Devlaner/devlane into forgo…
nazarli-shabnam ee3e944
fix: catch block now uses getApiErrorMessage(err)
nazarli-shabnam e9cdf2e
fix: no longer duplicate the helpers
nazarli-shabnam 496e86f
fix: validated check
nazarli-shabnam c4d79c5
fix: linting fixed
nazarli-shabnam aaeacba
fix: run prettier in pre-commit
nazarli-shabnam 13be175
Merge branch 'main' of https://github.com/Devlaner/devlane into forgo…
nazarli-shabnam 43bc47e
fix: set all three explicitly: API_PUBLIC_URL, FRONTEND_PUBLIC_URL, A…
nazarli-shabnam e284e65
feat: Built from API_PUBLIC_URL, fallback to request host if unset (w…
nazarli-shabnam 9e6e8c5
fix: 000002 = password_reset_tokens, accounts uses access_token_expir…
nazarli-shabnam 43932fe
fix: empty string keeps requests relative in prod
nazarli-shabnam 9ab12ad
fix: magic code vs password login, parallel tests, clipboard
nazarli-shabnam 0eebb99
fix: Lax, not Strict
nazarli-shabnam 6599acc
feat: requires an SMTP host in the instance email settings and return…
nazarli-shabnam a8e71f3
fix: server signout uses same session source as auth middleware; redu…
nazarli-shabnam File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package model | ||
|
|
||
| import ( | ||
| "time" | ||
|
|
||
| "github.com/google/uuid" | ||
| ) | ||
|
|
||
| // PasswordResetToken stores a one-time token for "forgot password" flows. | ||
| type PasswordResetToken struct { | ||
| ID uuid.UUID `gorm:"type:uuid;primaryKey;default:gen_random_uuid()"` | ||
| UserID uuid.UUID `gorm:"type:uuid;not null;index"` | ||
| Token string `gorm:"type:varchar(64);uniqueIndex;not null"` | ||
| ExpiresAt time.Time `gorm:"not null"` | ||
| UsedAt *time.Time | ||
| CreatedAt time.Time | ||
| } | ||
|
|
||
| func (PasswordResetToken) TableName() string { return "password_reset_tokens" } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| package store | ||
|
|
||
| import ( | ||
| "context" | ||
| "crypto/rand" | ||
| "encoding/hex" | ||
| "time" | ||
|
|
||
| "github.com/Devlaner/devlane/api/internal/model" | ||
| "github.com/google/uuid" | ||
| "gorm.io/gorm" | ||
| ) | ||
|
|
||
| const resetTokenExpireMinutes = 30 | ||
|
|
||
| type PasswordResetTokenStore struct{ db *gorm.DB } | ||
|
|
||
| func NewPasswordResetTokenStore(db *gorm.DB) *PasswordResetTokenStore { | ||
| return &PasswordResetTokenStore{db: db} | ||
| } | ||
|
|
||
| // Create generates a cryptographically random token, stores it, and returns the plain token. | ||
| func (s *PasswordResetTokenStore) Create(ctx context.Context, userID uuid.UUID) (string, error) { | ||
| // Invalidate any existing unused tokens for this user. | ||
| s.db.WithContext(ctx). | ||
| Where("user_id = ? AND used_at IS NULL", userID). | ||
| Delete(&model.PasswordResetToken{}) | ||
|
|
||
|
martian56 marked this conversation as resolved.
Outdated
|
||
| b := make([]byte, 32) | ||
| if _, err := rand.Read(b); err != nil { | ||
| return "", err | ||
| } | ||
| token := hex.EncodeToString(b) | ||
| rec := &model.PasswordResetToken{ | ||
| ID: uuid.New(), | ||
| UserID: userID, | ||
| Token: token, | ||
| ExpiresAt: time.Now().UTC().Add(time.Duration(resetTokenExpireMinutes) * time.Minute), | ||
| } | ||
| if err := s.db.WithContext(ctx).Create(rec).Error; err != nil { | ||
| return "", err | ||
| } | ||
| return token, nil | ||
| } | ||
|
|
||
| // GetValid returns the token record if it exists, has not expired, and has not been used. | ||
| func (s *PasswordResetTokenStore) GetValid(ctx context.Context, token string) (*model.PasswordResetToken, error) { | ||
| var rec model.PasswordResetToken | ||
| err := s.db.WithContext(ctx). | ||
| Where("token = ? AND expires_at > ? AND used_at IS NULL", token, time.Now().UTC()). | ||
| First(&rec).Error | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| return &rec, nil | ||
| } | ||
|
|
||
| // MarkUsed sets used_at so the token cannot be reused. | ||
| func (s *PasswordResetTokenStore) MarkUsed(ctx context.Context, id uuid.UUID) error { | ||
| now := time.Now().UTC() | ||
| return s.db.WithContext(ctx). | ||
| Model(&model.PasswordResetToken{}). | ||
| Where("id = ?", id). | ||
| Update("used_at", now).Error | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| DROP TABLE IF EXISTS password_reset_tokens; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| CREATE TABLE IF NOT EXISTS password_reset_tokens ( | ||
| id UUID PRIMARY KEY DEFAULT gen_random_uuid(), | ||
|
martian56 marked this conversation as resolved.
Outdated
|
||
| user_id UUID NOT NULL REFERENCES users (id) ON DELETE CASCADE, | ||
| token VARCHAR(64) NOT NULL UNIQUE, | ||
| expires_at TIMESTAMPTZ NOT NULL, | ||
| used_at TIMESTAMPTZ, | ||
| created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() | ||
| ); | ||
| CREATE INDEX IF NOT EXISTS idx_password_reset_tokens_user ON password_reset_tokens (user_id); | ||
| CREATE INDEX IF NOT EXISTS idx_password_reset_tokens_token ON password_reset_tokens (token); | ||
|
martian56 marked this conversation as resolved.
Outdated
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.