feat: add Go models for User and UserProfile
- Create models/user.go with bcrypt password hashing - Create models/user_profile.go with foreign key relationship - Add GORM hooks for automatic profile creation - Include proper JSON tags and database constraints
This commit is contained in:
		
							parent
							
								
									e40a119bdc
								
							
						
					
					
						commit
						3ed698918b
					
				
					 5 changed files with 52 additions and 75 deletions
				
			
		|  | @ -1,40 +0,0 @@ | ||||||
| from models.UserProfile.user_profile import UserProfile |  | ||||||
| from werkzeug.security import generate_password_hash, check_password_hash |  | ||||||
| from models import db |  | ||||||
| from sqlalchemy import event |  | ||||||
| 
 |  | ||||||
| class User(db.Model): |  | ||||||
|     __tablename__ = 'users' |  | ||||||
|      |  | ||||||
|     id = db.Column(db.Integer, primary_key=True) |  | ||||||
|     username = db.Column(db.String(80), unique=True, nullable=False) |  | ||||||
|     email = db.Column(db.String(120), unique=True, nullable=False)  # Add email field |  | ||||||
|     _password = db.Column("password", db.String(255), nullable=False)     |  | ||||||
|      |  | ||||||
|     profile = db.relationship('UserProfile', back_populates='user', uselist=False, cascade="all, delete-orphan") |  | ||||||
|          |  | ||||||
|     @property |  | ||||||
|     def password(self): |  | ||||||
|         return self._password |  | ||||||
| 
 |  | ||||||
|     @password.setter |  | ||||||
|     def password(self, raw_password): |  | ||||||
|         if not raw_password.startswith("pbkdf2:sha256:"): |  | ||||||
|             self._password = generate_password_hash(raw_password) |  | ||||||
|         else: |  | ||||||
|             self._password = raw_password |  | ||||||
| 
 |  | ||||||
|     def check_password(self, password): |  | ||||||
|         return check_password_hash(self._password, password) |  | ||||||
|      |  | ||||||
| @event.listens_for(User, 'after_insert') |  | ||||||
| def create_user_profile(mapper, connection, target): |  | ||||||
|     connection.execute( |  | ||||||
|         UserProfile.__table__.insert().values( |  | ||||||
|             user_id=target.id, |  | ||||||
|             first_name="", |  | ||||||
|             last_name="", |  | ||||||
|             bio="", |  | ||||||
|             profile_picture="" |  | ||||||
|         ) |  | ||||||
|     ) |  | ||||||
|  | @ -1,13 +0,0 @@ | ||||||
| from models import db |  | ||||||
| 
 |  | ||||||
| class UserProfile(db.Model): |  | ||||||
|     __tablename__ = 'user_profiles' |  | ||||||
|      |  | ||||||
|     id = db.Column(db.Integer, primary_key=True) |  | ||||||
|     user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) |  | ||||||
|     first_name = db.Column(db.String(50), nullable=False, default="") |  | ||||||
|     last_name = db.Column(db.String(50), nullable=False, default="") |  | ||||||
|     bio = db.Column(db.Text, default="") |  | ||||||
|     profile_picture = db.Column(db.String(255), default="") |  | ||||||
|      |  | ||||||
|     user = db.relationship('User', back_populates='profile') |  | ||||||
|  | @ -1,22 +0,0 @@ | ||||||
| import os |  | ||||||
| from flask_sqlalchemy import SQLAlchemy |  | ||||||
| from dotenv import load_dotenv |  | ||||||
| from urllib.parse import quote_plus |  | ||||||
| 
 |  | ||||||
| load_dotenv() |  | ||||||
| 
 |  | ||||||
| PG_USER = quote_plus(os.getenv("PG_USER", "postgres")) |  | ||||||
| PG_PASSWORD = quote_plus(os.getenv("PG_PASSWORD", "postgres")) |  | ||||||
| PG_HOST = os.getenv("PG_HOST", "localhost") |  | ||||||
| PG_PORT = os.getenv("PG_PORT", "5432") |  | ||||||
| PG_DATABASE = os.getenv("PG_DATABASE", "rideaware") |  | ||||||
| 
 |  | ||||||
| DATABASE_URI = f"postgresql+psycopg2://{PG_USER}:{PG_PASSWORD}@{PG_HOST}:{PG_PORT}/{PG_DATABASE}" |  | ||||||
| 
 |  | ||||||
| db = SQLAlchemy() |  | ||||||
| 
 |  | ||||||
| def init_db(app): |  | ||||||
|     """Initialize the SQLAlchemy app with the configuration.""" |  | ||||||
|     app.config['SQLALCHEMY_DATABASE_URI'] = DATABASE_URI |  | ||||||
|     app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False |  | ||||||
|     db.init_app(app) |  | ||||||
							
								
								
									
										40
									
								
								models/user.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								models/user.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | ||||||
|  | package models | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"golang.org/x/crypto/bcrypt" | ||||||
|  | 	"gorm.io/gorm" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type User struct { | ||||||
|  | 	ID       uint   `gorm:"primaryKey" json:"id"` | ||||||
|  | 	Username string `gorm:"unique;not null;size:80" json:"username"` | ||||||
|  | 	Email    string `gorm:"unique;not null;size:255" json:"email"` // Add this line | ||||||
|  | 	Password string `gorm:"not null;size:255" json:"-"` | ||||||
|  | 
 | ||||||
|  | 	Profile *UserProfile `gorm:"constraint:OnDelete:CASCADE;" json:"profile,omitempty"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (u *User) SetPassword(password string) error { | ||||||
|  | 	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	u.Password = string(hashedPassword) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (u *User) CheckPassword(password string) bool { | ||||||
|  | 	err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password)) | ||||||
|  | 	return err == nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (u *User) AfterCreate(tx *gorm.DB) error { | ||||||
|  | 	profile := UserProfile{ | ||||||
|  | 		UserID:         u.ID, | ||||||
|  | 		FirstName:      "", | ||||||
|  | 		LastName:       "", | ||||||
|  | 		Bio:            "", | ||||||
|  | 		ProfilePicture: "", | ||||||
|  | 	} | ||||||
|  | 	return tx.Create(&profile).Error | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								models/user_profile.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								models/user_profile.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | ||||||
|  | package models | ||||||
|  | 
 | ||||||
|  | type UserProfile struct { | ||||||
|  | 	ID             uint   `gorm:"primaryKey" json:"id"` | ||||||
|  | 	UserID         uint   `gorm:"not null" json:"user_id"` | ||||||
|  | 	FirstName      string `gorm:"size:80;not null" json:"first_name"` | ||||||
|  | 	LastName       string `gorm:"size:80;not null" json:"last_name"` | ||||||
|  | 	Bio            string `gorm:"type:text" json:"bio"` | ||||||
|  | 	ProfilePicture string `gorm:"size:255" json:"profile_picture"` | ||||||
|  | 
 | ||||||
|  | 	User *User `gorm:"foreignKey:UserID" json:"user,omitempty"` | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Cipher Vance
						Cipher Vance