Squash TypeScript errors and fix bugs
Most errors highglighted by TS were due to a lack of type definitions and were ignored by settings types to `any`. Some minor bugs were resolved where the fix was obvious. TODO marks left where `any` needs to be later removed or bugfix verified
This commit is contained in:
parent
c92c4cded3
commit
4421930942
15
app/package-lock.json
generated
15
app/package-lock.json
generated
@ -1054,6 +1054,21 @@
|
||||
"integrity": "sha512-ui3WwXmjTaY73fOQ3/m3nnajU/Orhi6cEu5rzX+BrAAJxa3eITXZ5ch9suPqtM03OWhAHhPSyBGCN4UKoxO20Q==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/jest": {
|
||||
"version": "24.0.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.17.tgz",
|
||||
"integrity": "sha512-1cy3xkOAfSYn78dsBWy4M3h/QF/HeWPchNFDjysVtp3GHeTdSmtluNnELfCmfNRRHo0OWEcpf+NsEJQvwQfdqQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/jest-diff": "20.0.1"
|
||||
}
|
||||
},
|
||||
"@types/jest-diff": {
|
||||
"version": "20.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/jest-diff/-/jest-diff-20.0.1.tgz",
|
||||
"integrity": "sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/mime": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz",
|
||||
|
@ -38,7 +38,9 @@
|
||||
"devDependencies": {
|
||||
"@types/express": "^4.17.0",
|
||||
"@types/express-session": "^1.15.13",
|
||||
"@types/jest": "^24.0.17",
|
||||
"@types/node": "^12.7.1",
|
||||
"@types/prop-types": "^15.7.1",
|
||||
"@types/react": "^16.9.0",
|
||||
"@types/react-dom": "^16.8.5",
|
||||
"@types/react-router-dom": "^4.3.4",
|
||||
|
@ -72,7 +72,7 @@ function queryBuildingsByReference(key, id) {
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
return { error: 'Key must be UPRN or TOID' };
|
||||
return Promise.resolve({ error: 'Key must be UPRN or TOID' });
|
||||
}
|
||||
|
||||
function getBuildingById(id) {
|
@ -8,7 +8,7 @@ import { hydrate } from 'react-dom';
|
||||
|
||||
import App from './frontend/app';
|
||||
|
||||
const data = window.__PRELOADED_STATE__;
|
||||
const data = (window as any).__PRELOADED_STATE__; // TODO: remove any
|
||||
|
||||
hydrate(
|
||||
<BrowserRouter>
|
||||
|
@ -15,10 +15,10 @@ const pgp = pg();
|
||||
// database connection (default to env vars)
|
||||
const db = pgp({
|
||||
'host': process.env.PGHOST,
|
||||
'dbname': process.env.PGDATABASE,
|
||||
'database': process.env.PGDATABASE,
|
||||
'user': process.env.PGUSER,
|
||||
'password': process.env.PGPASSWORD,
|
||||
'port': process.env.PGPORT
|
||||
'port': parseInt(process.env.PGPORT)
|
||||
});
|
||||
|
||||
export default db;
|
@ -31,7 +31,13 @@ import { parseCategoryURL } from '../parse';
|
||||
* map or other pages are rendered, based on the URL. Use a react-router-dom <Link /> in
|
||||
* child components to navigate without a full page reload.
|
||||
*/
|
||||
class App extends React.Component {
|
||||
class App extends React.Component<any, any> { // TODO: add proper types
|
||||
static propTypes = { // TODO: generate propTypes from TS
|
||||
user: PropTypes.object,
|
||||
building: PropTypes.object,
|
||||
building_like: PropTypes.bool
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
// set building revision id, default 0
|
||||
@ -130,7 +136,7 @@ class App extends React.Component {
|
||||
colourBuilding(building) {
|
||||
const cat = parseCategoryURL(window.location.pathname);
|
||||
const q = parse(window.location.search);
|
||||
const data = (cat === 'like')? {like: true}: JSON.parse(q.data);
|
||||
const data = (cat === 'like')? {like: true}: JSON.parse(q.data as string); // TODO: verify what happens if data is string[]
|
||||
if (cat === 'like'){
|
||||
this.likeBuilding(building.building_id)
|
||||
} else {
|
||||
@ -257,12 +263,6 @@ class App extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
App.propTypes = {
|
||||
user: PropTypes.object,
|
||||
building: PropTypes.object,
|
||||
building_like: PropTypes.bool
|
||||
}
|
||||
|
||||
/**
|
||||
* Component to fall back on in case of 404 or no other match
|
||||
*/
|
||||
|
@ -47,17 +47,36 @@ BuildingEdit.propTypes = {
|
||||
building_id: PropTypes.number
|
||||
}
|
||||
|
||||
class EditForm extends Component {
|
||||
class EditForm extends Component<any, any> { // TODO: add proper types
|
||||
static propTypes = { // TODO: generate propTypes from TS
|
||||
title: PropTypes.string,
|
||||
slug: PropTypes.string,
|
||||
cat: PropTypes.string,
|
||||
help: PropTypes.string,
|
||||
error: PropTypes.object,
|
||||
like: PropTypes.bool,
|
||||
building_like: PropTypes.bool,
|
||||
selectBuilding: PropTypes.func,
|
||||
building_id: PropTypes.number,
|
||||
inactive: PropTypes.bool,
|
||||
fields: PropTypes.array
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
// create object and spread into state to avoid TS complaining about modifying readonly state
|
||||
let fieldsObj = {};
|
||||
for (const field of props.fields) {
|
||||
fieldsObj[field.slug] = props[field.slug];
|
||||
}
|
||||
|
||||
this.state = {
|
||||
error: this.props.error || undefined,
|
||||
like: this.props.like || undefined,
|
||||
copying: false,
|
||||
keys_to_copy: {}
|
||||
}
|
||||
for (const field of props.fields) {
|
||||
this.state[field.slug] = props[field.slug]
|
||||
keys_to_copy: {},
|
||||
...fieldsObj
|
||||
}
|
||||
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
@ -353,20 +372,6 @@ class EditForm extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
EditForm.propTypes = {
|
||||
title: PropTypes.string,
|
||||
slug: PropTypes.string,
|
||||
cat: PropTypes.string,
|
||||
help: PropTypes.string,
|
||||
error: PropTypes.object,
|
||||
like: PropTypes.bool,
|
||||
building_like: PropTypes.bool,
|
||||
selectBuilding: PropTypes.func,
|
||||
building_id: PropTypes.number,
|
||||
inactive: PropTypes.bool,
|
||||
fields: PropTypes.array
|
||||
}
|
||||
|
||||
const TextInput = (props) => (
|
||||
<Fragment>
|
||||
<Label slug={props.slug} title={props.title} tooltip={props.tooltip}
|
||||
@ -424,7 +429,20 @@ LongTextInput.propTypes = {
|
||||
handleChange: PropTypes.func
|
||||
}
|
||||
|
||||
class MultiTextInput extends Component {
|
||||
class MultiTextInput extends Component<any, any> { // TODO: add proper types
|
||||
static propTypes = { // TODO: generate propTypes from TS
|
||||
slug: PropTypes.string,
|
||||
title: PropTypes.string,
|
||||
tooltip: PropTypes.string,
|
||||
value: PropTypes.arrayOf(PropTypes.string),
|
||||
placeholder: PropTypes.string,
|
||||
disabled: PropTypes.bool,
|
||||
handleChange: PropTypes.func,
|
||||
copy: PropTypes.bool,
|
||||
toggleCopyAttribute: PropTypes.func,
|
||||
copying: PropTypes.bool
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.edit = this.edit.bind(this);
|
||||
@ -497,19 +515,6 @@ class MultiTextInput extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
MultiTextInput.propTypes = {
|
||||
slug: PropTypes.string,
|
||||
title: PropTypes.string,
|
||||
tooltip: PropTypes.string,
|
||||
value: PropTypes.arrayOf(PropTypes.string),
|
||||
placeholder: PropTypes.string,
|
||||
disabled: PropTypes.bool,
|
||||
handleChange: PropTypes.func,
|
||||
copy: PropTypes.bool,
|
||||
toggleCopyAttribute: PropTypes.func,
|
||||
copying: PropTypes.bool
|
||||
}
|
||||
|
||||
const TextListInput = (props) => (
|
||||
<Fragment>
|
||||
<Label slug={props.slug} title={props.title} tooltip={props.tooltip}
|
||||
@ -521,7 +526,7 @@ const TextListInput = (props) => (
|
||||
id={props.slug} name={props.slug}
|
||||
value={props.value || ''}
|
||||
disabled={props.disabled}
|
||||
list={`${props.slug}_suggestions`}
|
||||
// list={`${props.slug}_suggestions`} TODO: investigate whether this was needed
|
||||
onChange={props.handleChange}>
|
||||
<option value="">Select a source</option>
|
||||
{
|
||||
@ -571,7 +576,22 @@ NumberInput.propTypes = {
|
||||
handleChange: PropTypes.func
|
||||
}
|
||||
|
||||
class YearEstimator extends Component {
|
||||
class YearEstimator extends Component<any, any> { // TODO: add proper types
|
||||
static propTypes = { // TODO: generate propTypes from TS
|
||||
slug: PropTypes.string,
|
||||
title: PropTypes.string,
|
||||
tooltip: PropTypes.string,
|
||||
date_year: PropTypes.number,
|
||||
date_upper: PropTypes.number,
|
||||
date_lower: PropTypes.number,
|
||||
value: PropTypes.number,
|
||||
disabled: PropTypes.bool,
|
||||
handleChange: PropTypes.func,
|
||||
copy: PropTypes.bool,
|
||||
toggleCopyAttribute: PropTypes.func,
|
||||
copying: PropTypes.bool
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@ -594,21 +614,6 @@ class YearEstimator extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
YearEstimator.propTypes = {
|
||||
slug: PropTypes.string,
|
||||
title: PropTypes.string,
|
||||
tooltip: PropTypes.string,
|
||||
date_year: PropTypes.number,
|
||||
date_upper: PropTypes.number,
|
||||
date_lower: PropTypes.number,
|
||||
value: PropTypes.number,
|
||||
disabled: PropTypes.bool,
|
||||
handleChange: PropTypes.func,
|
||||
copy: PropTypes.bool,
|
||||
toggleCopyAttribute: PropTypes.func,
|
||||
copying: PropTypes.bool
|
||||
}
|
||||
|
||||
const CheckboxInput = (props) => (
|
||||
<Fragment>
|
||||
<Label slug={props.slug} title={props.title} tooltip={props.tooltip}
|
||||
@ -675,7 +680,7 @@ LikeButton.propTypes = {
|
||||
handleLike: PropTypes.func
|
||||
}
|
||||
|
||||
const Label = (props) => {
|
||||
const Label: React.SFC<any> = (props) => { // TODO: remove any
|
||||
return (
|
||||
<label htmlFor={props.slug}>
|
||||
{props.title}
|
||||
|
@ -46,7 +46,18 @@ BuildingView.propTypes = {
|
||||
building_like: PropTypes.bool
|
||||
}
|
||||
|
||||
class DataSection extends React.Component {
|
||||
class DataSection extends React.Component<any, any> { // TODO: add proper types
|
||||
static propTypes = { // TODO: generate propTypes from TS
|
||||
title: PropTypes.string,
|
||||
cat: PropTypes.string,
|
||||
slug: PropTypes.string,
|
||||
intro: PropTypes.string,
|
||||
help: PropTypes.string,
|
||||
inactive: PropTypes.bool,
|
||||
building_id: PropTypes.number,
|
||||
children: PropTypes.node
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@ -194,18 +205,7 @@ class DataSection extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
DataSection.propTypes = {
|
||||
title: PropTypes.string,
|
||||
cat: PropTypes.string,
|
||||
slug: PropTypes.string,
|
||||
intro: PropTypes.string,
|
||||
help: PropTypes.string,
|
||||
inactive: PropTypes.bool,
|
||||
building_id: PropTypes.number,
|
||||
children: PropTypes.node
|
||||
}
|
||||
|
||||
const DataEntry = (props) => {
|
||||
const DataEntry: React.SFC<any> = (props) => { // TODO: remove any
|
||||
return (
|
||||
<Fragment>
|
||||
<dt>
|
||||
@ -241,9 +241,9 @@ DataEntry.propTypes = {
|
||||
value: PropTypes.any
|
||||
}
|
||||
|
||||
const LikeDataEntry = (props) => {
|
||||
const LikeDataEntry: React.SFC<any> = (props) => { // TODO: remove any
|
||||
const data_string = JSON.stringify({like: true});
|
||||
(
|
||||
return (
|
||||
<Fragment>
|
||||
<dt>
|
||||
{ props.title }
|
||||
@ -280,7 +280,7 @@ LikeDataEntry.propTypes = {
|
||||
user_building_like: PropTypes.bool
|
||||
}
|
||||
|
||||
const MultiDataEntry = (props) => {
|
||||
const MultiDataEntry: React.SFC<any> = (props) => { // TODO: remove any
|
||||
let content;
|
||||
|
||||
if (props.value && props.value.length) {
|
||||
|
@ -8,7 +8,13 @@ import './header.css';
|
||||
/**
|
||||
* Render the main header using a responsive design
|
||||
*/
|
||||
class Header extends React.Component {
|
||||
class Header extends React.Component<any, any> { // TODO: add proper types
|
||||
static propTypes = { // TODO: generate propTypes from TS
|
||||
user: PropTypes.shape({
|
||||
username: PropTypes.string
|
||||
})
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {collapseMenu: true};
|
||||
@ -106,10 +112,4 @@ class Header extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
Header.propTypes = {
|
||||
user: PropTypes.shape({
|
||||
username: PropTypes.string
|
||||
})
|
||||
}
|
||||
|
||||
export default Header;
|
||||
|
@ -97,7 +97,12 @@ const LEGEND_CONFIG = {
|
||||
};
|
||||
|
||||
|
||||
class Legend extends React.Component {
|
||||
class Legend extends React.Component<any, any> { // TODO: add proper types
|
||||
static propTypes = { // TODO: generate propTypes from TS
|
||||
slug: PropTypes.string,
|
||||
color: PropTypes.string,
|
||||
text: PropTypes.string
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -195,11 +200,4 @@ class Legend extends React.Component {
|
||||
|
||||
}
|
||||
|
||||
|
||||
Legend.propTypes = {
|
||||
slug: PropTypes.string,
|
||||
color: PropTypes.string,
|
||||
text: PropTypes.string
|
||||
}
|
||||
|
||||
export default Legend;
|
||||
|
@ -6,7 +6,12 @@ import ErrorBox from './error-box';
|
||||
import InfoBox from './info-box';
|
||||
import SupporterLogos from './supporter-logos';
|
||||
|
||||
class Login extends Component {
|
||||
class Login extends Component<any, any> { // TODO: add proper types
|
||||
static propTypes = { // TODO: generate propTypes from TS
|
||||
login: PropTypes.func,
|
||||
user: PropTypes.object
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@ -127,9 +132,4 @@ class Login extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
Login.propTypes = {
|
||||
login: PropTypes.func,
|
||||
user: PropTypes.object
|
||||
}
|
||||
|
||||
export default Login;
|
||||
|
@ -16,7 +16,15 @@ const OS_API_KEY = 'NVUxtY5r8eA6eIfwrPTAGKrAAsoeI9E9';
|
||||
/**
|
||||
* Map area
|
||||
*/
|
||||
class ColouringMap extends Component {
|
||||
class ColouringMap extends Component<any, any> { // TODO: add proper types
|
||||
static propTypes = { // TODO: generate propTypes from TS
|
||||
building: PropTypes.object,
|
||||
revision_id: PropTypes.number,
|
||||
selectBuilding: PropTypes.func,
|
||||
colourBuilding: PropTypes.func,
|
||||
match: PropTypes.object,
|
||||
history: PropTypes.object
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -167,13 +175,4 @@ class ColouringMap extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
ColouringMap.propTypes = {
|
||||
building: PropTypes.object,
|
||||
revision_id: PropTypes.number,
|
||||
selectBuilding: PropTypes.func,
|
||||
colourBuilding: PropTypes.func,
|
||||
match: PropTypes.object,
|
||||
history: PropTypes.object
|
||||
}
|
||||
|
||||
export default ColouringMap;
|
||||
|
@ -35,7 +35,7 @@ const MultiEdit = (props) => {
|
||||
}
|
||||
|
||||
const q = parse(props.location.search);
|
||||
const data = JSON.parse(q.data)
|
||||
const data = JSON.parse(q.data as string) // TODO: verify what happens when data is string[]
|
||||
const title = sectionTitleFromCat(cat);
|
||||
return (
|
||||
<Sidebar
|
||||
@ -116,7 +116,7 @@ function fieldTitleFromSlug(slug) {
|
||||
(prev, section) => {
|
||||
const el = prev.concat(
|
||||
section.fields.filter(
|
||||
field => field.slug === slug
|
||||
(field: any) => field.slug === slug // TODO: remove any
|
||||
)
|
||||
)
|
||||
return el
|
||||
|
@ -4,7 +4,19 @@ import PropTypes from 'prop-types';
|
||||
|
||||
import ErrorBox from './error-box';
|
||||
|
||||
class MyAccountPage extends Component {
|
||||
class MyAccountPage extends Component<any, any> { // TODO: add proper types
|
||||
static propTypes = { // TODO: generate propTypes from TS
|
||||
user: PropTypes.shape({
|
||||
username: PropTypes.string,
|
||||
email: PropTypes.string,
|
||||
registered: PropTypes.instanceOf(Date), // TODO: check if fix correct
|
||||
api_key: PropTypes.string,
|
||||
error: PropTypes.object
|
||||
}),
|
||||
updateUser: PropTypes.func,
|
||||
logout: PropTypes.func
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@ -110,16 +122,4 @@ class MyAccountPage extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
MyAccountPage.propTypes = {
|
||||
user: PropTypes.shape({
|
||||
username: PropTypes.string,
|
||||
email: PropTypes.string,
|
||||
registered: PropTypes.date,
|
||||
api_key: PropTypes.string,
|
||||
error: PropTypes.object
|
||||
}),
|
||||
updateUser: PropTypes.func,
|
||||
logout: PropTypes.func
|
||||
}
|
||||
|
||||
export default MyAccountPage;
|
||||
|
@ -6,7 +6,11 @@ import { SearchIcon } from './icons';
|
||||
/**
|
||||
* Search for location
|
||||
*/
|
||||
class SearchBox extends Component {
|
||||
class SearchBox extends Component<any, any> { // TODO: add proper types
|
||||
static propTypes = { // TODO: generate propTypes from TS
|
||||
onLocate: PropTypes.func,
|
||||
isBuilding: PropTypes.bool
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -178,9 +182,4 @@ class SearchBox extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
SearchBox.propTypes = {
|
||||
onLocate: PropTypes.func,
|
||||
isBuilding: PropTypes.bool
|
||||
}
|
||||
|
||||
export default SearchBox;
|
||||
|
@ -6,7 +6,12 @@ import ErrorBox from './error-box';
|
||||
import InfoBox from './info-box';
|
||||
import SupporterLogos from './supporter-logos';
|
||||
|
||||
class SignUp extends Component {
|
||||
class SignUp extends Component<any, any> { // TODO: add proper types
|
||||
static propTypes = { // TODO: generate propTypes from TS
|
||||
login: PropTypes.func.isRequired,
|
||||
user: PropTypes.object
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@ -157,9 +162,4 @@ class SignUp extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
SignUp.propTypes = {
|
||||
login: PropTypes.func.isRequired,
|
||||
user: PropTypes.object
|
||||
}
|
||||
|
||||
export default SignUp;
|
||||
|
@ -4,7 +4,11 @@ import PropTypes from 'prop-types';
|
||||
import './tooltip.css';
|
||||
import { InfoIcon } from './icons';
|
||||
|
||||
class Tooltip extends Component {
|
||||
class Tooltip extends Component<any, any> { // TODO: add proper types
|
||||
static propTypes = { // TODO: generate propTypes from TS
|
||||
text: PropTypes.string
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
@ -44,8 +48,4 @@ class Tooltip extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
Tooltip.propTypes = {
|
||||
text: PropTypes.string
|
||||
}
|
||||
|
||||
export default Tooltip;
|
||||
|
@ -10,12 +10,10 @@ const server = http.createServer(app);
|
||||
|
||||
let currentApp = app;
|
||||
|
||||
server.listen(process.env.PORT || 3000, error => {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
server.listen(process.env.PORT || 3000, () => {
|
||||
console.log('🚀 started');
|
||||
}).on('error', error => {
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
// In development mode, enable hot module reloading (HMR)
|
@ -48,7 +48,7 @@ server.use(bodyParser.json());
|
||||
|
||||
// handle user sessions
|
||||
const pgSession = pgConnect(session);
|
||||
const sess = {
|
||||
const sess: any = { // TODO: remove any
|
||||
name: 'cl.session',
|
||||
store: new pgSession({
|
||||
pgPromise: db,
|
||||
@ -72,8 +72,8 @@ server.get('/*.html', frontendRoute);
|
||||
server.get('/', frontendRoute);
|
||||
|
||||
function frontendRoute(req, res) {
|
||||
const context = {};
|
||||
const data = {};
|
||||
const context: any = {}; // TODO: remove any
|
||||
const data: any = {}; // TODO: remove any
|
||||
context.status = 200;
|
||||
|
||||
const userId = req.session.user_id;
|
||||
@ -339,7 +339,7 @@ server.post('/users', function (req, res) {
|
||||
|
||||
// POST user auth
|
||||
server.post('/login', function (req, res) {
|
||||
authUser(req.body.username, req.body.password).then(function (user) {
|
||||
authUser(req.body.username, req.body.password).then(function (user: any) { // TODO: remove any
|
||||
if (user.user_id) {
|
||||
req.session.user_id = user.user_id;
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user